springboot快速搭建ftpserver服务端的详细步骤

 更新时间:2023年11月03日 14:29:35   作者:汤姆猫不是猫  
基于springboot,使用ftpserver快速搭建一个FTP服务端,搭建过程很简单,我们把过程分成4个步骤,一分钟内快速完成构建,感兴趣的朋友跟随小编一起看看吧

前言

基于springboot,使用ftpserver快速搭建一个FTP服务端。

搭建过程很简单,我们把过程分成4个步骤,一分钟内快速完成构建。

实现功能

  • 使用ftpserver快速搭建一个FTP服务端
  • 支持多个用户多个目录上传目录
  • 支持FTP主动模式(单个端口)和被动模式(范围随机端口)
  • 监听ftpserver状态,方便进行更细粒度权限控制等定制功能

依赖项

gradle方式:

 implementation 'org.apache.ftpserver:ftpserver-core:1.2.0'

maven方式

<dependency>
    <groupId>org.apache.ftpserver</groupId>
    <artifactId>ftpserver-core</artifactId>
    <version>1.2.0</version>
</dependency>
<dependency>
    <groupId>org.apache.ftpserver</groupId>
    <artifactId>ftpserver-core</artifactId>
    <version>1.2.0</version>
</dependency>

配置文件

首先,在springboot项目中增加两个配置,创建ftpserver.properties配置和在application.properties基础上增加ftp配置。配置如下:

1、ftpserver.properties配置

#表示admin的密码是12345,以下都是admin的参数设置,可以设置多个用户
ftpserver.user.admin.userpassword=eguid
ftpserver.user.admin.homedirectory=C://ftp
ftpserver.user.admin.enableflag=true
ftpserver.user.admin.writepermission=true
ftpserver.user.admin.maxloginnumber=0
ftpserver.user.admin.maxloginperip=0
ftpserver.user.admin.idletime=0
ftpserver.user.admin.uploadrate=0
ftpserver.user.admin.downloadrate=0
#用户名是eguid的用户配置
ftpserver.user.eguid.userpassword=eguid
ftpserver.user.eguid.homedirectory=C://ftp/eguid
ftpserver.user.eguid.enableflag=true
ftpserver.user.eguid.writepermission=true
ftpserver.user.eguid.maxloginnumber=0
ftpserver.user.eguid.maxloginperip=0
ftpserver.user.eguid.idletime=0
ftpserver.user.eguid.uploadrate=0
ftpserver.user.eguid.downloadrate=0

2、application.properties配置

在原有application.properties基础上增加以下配置

##FTP内嵌服务器
#ftp连接端口
ftp.port=8021
# ftp主动模式端口
ftp.activePort=8022
#ftp被动模式数据传输端口
ftp.passivePorts=50021-60021

初始化FTP服务

该类继承自ApplicationRunner类,会在springboot服务启动后自动启动。
由于没有考虑到springboot重启的情况,所以ftp服务会出现无法释放端口的问题,解决该问题请参考博主另一篇文章《springboot内嵌ftpserver服务端在服务重启后报错端口被占用解决办法》,就可以解决跟随springboot重启ftp服务的问题。

import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.ftplet.FtpException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
 * 初始化ftp服务器
 * @author 汤姆猫不是猫
 */
@Component
public class InitFtpServer implements ApplicationRunner {
    public static final Logger log = LoggerFactory.getLogger(InitFtpServer.class);
    @Autowired
    private FtpServer server;
    @Override
    public void run(ApplicationArguments args) throws Exception {
        try {
            server.start();
            log.info("汤姆猫不是猫: ftp server start success ");
        } catch (FtpException e) {
            e.printStackTrace();
            log.error("汤姆猫不是猫: ftp server start error {}", e);
        }
    }
}

ftpserver服务主动模式和被动模式参数配置

import org.apache.ftpserver.DataConnectionConfigurationFactory;
import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.ftplet.Ftplet;
import org.apache.ftpserver.listener.ListenerFactory;
import org.apache.ftpserver.usermanager.ClearTextPasswordEncryptor;
import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import java.util.HashMap;
import java.util.Map;
/**
 * ftpserver配置,含主动模式和被动模式
 * @author 汤姆猫不是猫
 */
@Configuration
public class FtpServerConfig extends CachingConfigurerSupport {
    @Value("${ftp.port}")
    private Integer ftpPort;
    @Value("${ftp.activePort}")
    private Integer ftpActivePort;
    @Value("${ftp.passivePorts}")
    private String ftpPassivePorts;
    @Bean
    public FtpServer createFtpServer() {
        FtpServerFactory serverFactory = new FtpServerFactory();
        ListenerFactory factory = new ListenerFactory();
        //这个只是控制端口,还有主动模式端口和被动模式下的某个范围端口
        factory.setPort(ftpPort);
        factory.setIdleTimeout(10);
        //被动模式
        DataConnectionConfigurationFactory dataConnectionConfigurationFactory = new DataConnectionConfigurationFactory();
        dataConnectionConfigurationFactory.setIdleTime(30);
        dataConnectionConfigurationFactory.setActiveLocalPort(ftpActivePort);//主动模式端口
        dataConnectionConfigurationFactory.setPassiveIpCheck(true);
        dataConnectionConfigurationFactory.setPassivePorts(ftpPassivePorts);被动模式使用的端口范围
        factory.setDataConnectionConfiguration(dataConnectionConfigurationFactory.createDataConnectionConfiguration());
        // 替换默认的监听器
        serverFactory.addListener("default", factory.createListener());
        PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
        try {
            ClassPathResource classPathResource = new ClassPathResource("ftpserver.properties");
            userManagerFactory.setUrl(classPathResource.getURL());
        } catch (Exception e) {
            throw new RuntimeException("汤姆猫不是猫:配置文件ftpserver.properties不存在");
        }
        userManagerFactory.setPasswordEncryptor(new ClearTextPasswordEncryptor());
        serverFactory.setUserManager(userManagerFactory.createUserManager());
        Map<String, Ftplet> m = new HashMap<String, Ftplet>();
        m.put("miaFtplet", new FtpServerListener());
        serverFactory.setFtplets(m);
        // 创建ftpserver
        FtpServer server = serverFactory.createServer();
        return server;
    }
}

监听ftp服务运行状态

import org.apache.ftpserver.ftplet.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
/**
 * 监听ftpserver服务上传和下载情况
 * @author 汤姆猫不是猫
 */
public class FtpServerListener extends DefaultFtplet {
    public static final Logger log = LoggerFactory.getLogger(FtpServerListener.class);
    /**
     * 开始连接
     */
    @Override
    public FtpletResult onConnect(FtpSession session) throws FtpException,
            IOException {
        UUID sessionId = session.getSessionId();
        if(sessionId!=null) {
            log.info("{}尝试登录ftpserver", sessionId.toString());
        }
        User user = session.getUser();
        if(user!=null&&user.getName()!=null){
            log.info("{}尝试使用用户名:{},密码:{}登录ftpserver.", sessionId.toString(), user.getName(), user.getPassword());
        }
        return super.onConnect(session);
    }
    /**
     * 关闭连接
     */
    @Override
    public FtpletResult onDisconnect(FtpSession session) throws FtpException,
            IOException {
        UUID sessionId = session.getSessionId();
        if(sessionId!=null) {
            log.info("{}关闭ftpserver连接", sessionId.toString());
        }
        User user = session.getUser();
        if(user!=null&&user.getName()!=null){
            log.info("{}用户名:{}关闭ftpserver连接.",  sessionId.toString(), user.getName());
        }
        return super.onDisconnect(session);
    }
    /**
     * 开始上传
     */
    @Override
    public FtpletResult onUploadStart(FtpSession session, FtpRequest request)
            throws FtpException, IOException {
        //获取上传文件的上传路径
        String path = session.getUser().getHomeDirectory();
        //自动创建上传路径
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }
        //获取上传用户
        String name = session.getUser().getName();
        //获取上传文件名
        String filename = request.getArgument();
        log.info("用户:'{}',上传文件到目录:'{}',文件名称为:'{}',状态:开始上传~", name, path, filename);
        return super.onUploadEnd(session, request);
    }
    /**
     * 上传完成
     */
    @Override
    public FtpletResult onUploadEnd(FtpSession session, FtpRequest request)
            throws FtpException, IOException {
        //获取上传文件的上传路径
        String path = session.getUser().getHomeDirectory();
        //获取上传用户
        String name = session.getUser().getName();
        //获取上传文件名
        String filename = request.getArgument();
        File file = new File(path + "/" + filename);
        if (file.exists()) {
            System.out.println(file);
        }
        log.info("用户:'{}',上传文件到目录:'{}',文件名称为:'{},状态:成功!'", name, path, filename);
        return super.onUploadStart(session, request);
    }
    @Override
    public FtpletResult onDownloadStart(FtpSession session, FtpRequest request) throws FtpException, IOException {
        return super.onDownloadStart(session, request);
    }
    @Override
    public FtpletResult onDownloadEnd(FtpSession session, FtpRequest request) throws FtpException, IOException {
        return super.onDownloadEnd(session, request);
    }
}

以上步骤完成后,启动springboot。使用ftpclient工具尝试连接配置文件里的8021控制端口,如以下图所示,可以看到已经连接成功。

到此这篇关于springboot快速搭建ftpserver服务端的文章就介绍到这了,更多相关springboot 搭建ftpserver服务端内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • mybatis拦截器及不生效的解决方法

    mybatis拦截器及不生效的解决方法

    本文主要介绍了mybatis拦截器及不生效的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • JAVA自定义注解详情

    JAVA自定义注解详情

    这篇文章主要介绍了Java自定义注解,结合实例形式总结分析了java常见的自定义注解类型、功能、用法及操作注意事项,需要的朋友可以参考下
    2021-10-10
  • Java实现LeetCode(54.螺旋矩阵)

    Java实现LeetCode(54.螺旋矩阵)

    这篇文章主要介绍了Java实现LeetCode(螺旋矩阵),本文列出题目和写题的思路。给出完整的解法代码,需要的朋友可以参考下
    2021-06-06
  • java中InputStream获取字节大小相关方法详解

    java中InputStream获取字节大小相关方法详解

    这篇文章主要给大家介绍了关于java中InputStream获取字节大小相关方法的相关资料,在Java中要实现读取文件大小,可以使用InputStream来读取文件的内容,并通过获取读取的字节数来得到文件的大小,需要的朋友可以参考下
    2023-11-11
  • spring cloud gateway集成hystrix全局断路器操作

    spring cloud gateway集成hystrix全局断路器操作

    这篇文章主要介绍了spring cloud gateway集成hystrix全局断路器操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • SpringBoot整合Ureport2报表及常见使用方法

    SpringBoot整合Ureport2报表及常见使用方法

    这篇文章主要介绍了SpringBoot整合Ureport2报表及常见使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • java随机抽取指定范围内不重复的n个数

    java随机抽取指定范围内不重复的n个数

    这篇文章主要为大家详细介绍了java随机抽取指定范围内不重复的n个数,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • Java 动态模拟操作系统进程调度算法

    Java 动态模拟操作系统进程调度算法

    这篇文章主要介绍了采用java语言编程模拟N个进程采用动态高优先权优先进程调度算法。文中代码具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2021-12-12
  • mybatis Plus 多表联合查询的实现示例

    mybatis Plus 多表联合查询的实现示例

    这篇文章主要介绍了mybatis Plus 多表联合查询的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • JDBC用法小结

    JDBC用法小结

    这篇文章主要介绍了JDBC用法,较为详细的分析了基于JDBC进行数据库操作的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2014-12-12

最新评论