java ftp服务器、监听文件上传

news/2024/7/8 5:09:58

引言

这里介绍 java创建 Ftp服务器, 并且监测客户端上传文件后,读取文件的操作。使用 hutool 创建Ftp客户端,使用 ftplet-api 下的 DefaultFtplet 进行文件监听。
这里有个小小的问题 DefaultFtplet 监听器是 ftp 依赖下的类,测试使用 Hutool 下的 Ftp 类,所以无法通过 Ftp 指定文件夹上传,只能上传 创建 Ftp 服务器 时 指定的文件夹

添加依赖


<dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
</dependency>

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

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

<dependency>
    <groupId>org.apache.mina</groupId>
    <artifactId>mina-core</artifactId>
    <version>2.0.16</version>
</dependency>

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.18</version>
</dependency>

yml配置文件 及配置类

这里提供一种,引入 ftp服务器 账号密码的方式,当然也可以写死或者其他方式引入

yml配置文件 定义账号 密码 端口号

ftp-server:
  port: 27    # 端口号
  username: ftp
  password: ftp

配置类

package com.esframework.project.kdzt.ftp.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

/**
 * @author Administrator
 */
@Data
@Component
@Configuration
@ConfigurationProperties(prefix = "ftp-server")
public class FtpProperties {

    private Integer port;

    private String username;

    private String password;
}

利用hutool代码 整合spring boot 创建 ftp服务端

配置监听器

package com.example.ftp.ftp2;

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;

/**
 * ftp服务器侦听器
 *
 * @date 2023/06/29
 */
public class FtpServerListener extends DefaultFtplet {
    public static final Logger log = LoggerFactory.getLogger(FtpServerListener.class);


    /**
     * 在连接* 开始连接@param session 会话
     *
     * @return {@link FtpletResult}
     * @throws FtpException ftp例外
     * @throws IOException  ioexception
     */
    @Override
    public FtpletResult onConnect(FtpSession session) throws FtpException, IOException {
        UUID sessionId = session.getSessionId();
        if (sessionId != null) {
            log.info("{}尝试登录ftpserver", sessionId);
        }
        User user = session.getUser();
        if (user != null && user.getName() != null) {
            assert sessionId != null;
            log.info("{}尝试使用用户名:{},密码:{}登录ftpserver.", sessionId, user.getName(), user.getPassword());
        }
        return super.onConnect(session);
    }

    /**
     * 在断开* 关闭连接@param session 会话
     *
     * @return {@link FtpletResult}
     * @throws FtpException ftp例外
     * @throws IOException  ioexception
     */
    @Override
    public FtpletResult onDisconnect(FtpSession session) throws FtpException, IOException {
        UUID sessionId = session.getSessionId();
        User user = session.getUser();
        if (sessionId != null) {
            log.info("{}关闭ftpserver连接", sessionId);
        }
        if (user != null && user.getName() != null) {
            assert sessionId != null;
            log.info("{}用户名:{}关闭ftpserver连接.", sessionId, user.getName());
        }
        return super.onDisconnect(session);
    }

    /**
     * 上传开始* 开始上传@param session 会话
     *
     * @param request 请求
     * @return {@link FtpletResult}
     * @throws FtpException ftp例外
     * @throws IOException  ioexception
     */
    @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);
    }

    /**
     * 在上传* 上传完成@param session 会话
     *
     * @param request 请求
     * @return {@link FtpletResult}
     * @throws FtpException ftp例外
     * @throws IOException  ioexception
     */
    @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()) {
            // 读取文件
            String filePath = String.format("%s\\%s", path, fileName);
            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);
    }
}

使用 ApplicationRunner 启动服务时,创建 ftp服务

package com.example.ftp.ftp2;

import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.ftp.SimpleFtpServer;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ftpserver.ftplet.Authority;
import org.apache.ftpserver.usermanager.impl.BaseUser;
import org.apache.ftpserver.usermanager.impl.WritePermission;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.List;

/**
 * ftp服务器
 *
 * @author Administrator
 * @date 2023/06/30
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class FtpServer implements ApplicationRunner {

    private final FtpProperties ftpProperties;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        BaseUser user = new BaseUser();
        user.setName(ftpProperties.getUsername());
        user.setPassword(ftpProperties.getPassword());
        // 配置上传的文件夹 没有就新建
        File folder = FileUtil.file("folder");
        if(!folder.exists()) {
            boolean mkdir = folder.mkdir();
        }
        user.setHomeDirectory("D:\ftp");
        user.setMaxIdleTime(0);
        user.setEnabled(true);
        //设置用户权限
        List<Authority> authorities = Lists.newArrayList();
        authorities.add(new WritePermission());
        user.setAuthorities(authorities);

        SimpleFtpServer simpleFtpServer = SimpleFtpServer.create().addUser(user).setPort(ftpProperties.getPort());
        // 配置监听器
        simpleFtpServer.addFtplet("folder", new FtpServerListener());
        simpleFtpServer.start();
        log.info("Ftp 开启=====》");
    }
}

注意:

测试

使用 hutool 进行测试

注意
下面使用 public boolean upload(String destPath, File file) 这个方法时 destPath 会根据 Ftp Server 创建时 user的 setHomeDirectory 参数变化,

  1. 不设置 setHomeDirectory 参数时,destPath 写全部路径,但是监听器无法获取 上传文件的全路径。
  2. 设置 setHomeDirectory 参数时, destPath 填写 / 就是 setHomeDirectory 定义的文件夹
package com.example.ftp.ftp;

import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.ftp.Ftp;

import java.io.IOException;

public class FtpTest {

    public static void main(String[] args) {
        Ftp ftp1 = new Ftp("192.168.2.141",27, "ftp", "ftp");
        try {
            ftp1.upload("/", FileUtil.file("D:\\FlFile\\1234.txt"));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
               ftp1.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}


http://lihuaxi.xjx100.cn/news/1293356.html

相关文章

基于SSM+jsp的二手车交易网站设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

labview 波形图表(waveform Chart)

波形图表&#xff08;waveform Chart&#xff09;是显示一条或多条曲线的特殊数值控件&#xff0c; 一般用于显示以恒定速率采集的数据。 波形图表会在缓冲区保留历史数据并在历史数据后添加新数据。 波形图表的默认数据缓冲区大小为1024个数据点。 &#xff08;右击波形图…

JavaSE基础语法--接口

接口在现实生活中比比皆是。比如电脑的USB接口&#xff0c;插座的接口。这些接口我们发现都是一样的规范。比如插座的有双孔插&#xff0c;有三孔插。那么对应就有双脚设备&#xff0c;和三脚的设备。从这我们就能摸清楚规律&#xff1a;接口就是统一规范的提供服务。Java中接口…

linux内核 fault-injection

实验环境raspi 4b 一、Fault注入功能基础架构 See also drivers/md/md-faulty.c and “every_nth” module option for scsi_debug. Available fault injection capabilities failslab injects slab allocation failures. (kmalloc(), kmem_cache_alloc(), …) fail_page_al…

强化学习专题:回合更新算法

21点&#xff08;Blackjack&#xff09; 游戏开始 玩家收到两张明牌&#xff0c;荷官发给自己一张明牌和一张暗牌 根据自己手中的牌和荷官的明牌&#xff0c;玩家需要决定是否要牌&#xff08;Hit&#xff09;或停牌&#xff08;Stand&#xff09; 选择要牌&#xff0c;荷官发一…

2022(一等奖)C23“城轨促交融,慢行赋新机”—TOD模式下城市慢行接驳与碳减排辅助出行系统

作品介绍 一、需求分析 1.1设计背景 “双碳”战略倡导绿色、环保、低碳的生活方式。加快降低碳排放步伐&#xff0c;有利于引导绿色技术创新&#xff0c;提高产业和经济的全球竞争力。碳中和目标对交通运输领域的可持续发展也提出重要要求。随着城市化的快速推进&#xff0c;…

基于人体姿势估计的舞蹈检测(AI Dance based on Human Pose Estimation)

人体姿势骨架以图形格式表示人的方向。本质上&#xff0c;它是一组坐标&#xff0c;可以连接起来描述人的姿势。骨架中的每个坐标都被称为一个部分(或一个关节&#xff0c;或一个关键点)。两个部分之间的有效连接称为一对(或分支)。下面是一个人体姿势骨架样本。 因此&#xff…

【计算机网络】数据链路层之随机接入-CSMA/CA协议(无线局域网)

1.概念 2.无线局域网可否实现碰撞检验CD 3.方案 CSMA/CA 碰撞避免 4. 两种帧间间隔 IFS 为什么需要等待DIFS? 为什么需要等待SIFS? 为什么还要退避一段时间才能使用信道&#xff1f; 5.退避算法 使用退避算法的情况 退避算法 举例 6.信道预约 7.虚拟载波监听 8.题目 9.解析 …