当前位置: 首页 > article >正文

SpringBoot使用hutool操作FTP

项目场景:

SpringBoot使用hutool操作FTP,可以实现从FTP服务器下载文件到本地,以及将本地文件上传到FTP服务器的功能。


实现步骤:

1、引入依赖

<dependency>
	<groupId>commons-net</groupId>
	<artifactId>commons-net</artifactId>
	<version>3.9.0</version>
</dependency>

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

2、yml配置 

ftp:
  # 服务器地址
  host: 127.0.0.1
  # 端口号
  port: 21
  # 用户名
  userName: test
  # 密码
  password: test

3、Config配置类

 我这里用的是static修饰的变量,方便工具类调用。

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

/**
 * ftp配置
 */
@Configuration
public class FtpConfig {

    /**
     * 服务器地址
     */
    private static String host;

    /**
     * 端口
     */
    private static Integer port;

    /**
     * 用户名
     */
    private static String userName;

    /**
     * 密码
     */
    private static String password;

    @Value("${ftp.host}")
    public void setHost(String host) {
        FtpConfig.host = host;
    }

    public static String getHost() {
        return host;
    }

    @Value("${ftp.port}")
    public void setPort(Integer port) {
        FtpConfig.port = port;
    }

    public static Integer getPort() {
        return port;
    }

    @Value("${ftp.userName}")
    public void setUserName(String userName) {
        FtpConfig.userName = userName;
    }

    public static String getUserName() {
        return userName;
    }

    @Value("${ftp.password}")
    public void setPassword(String password) {
        FtpConfig.password = password;
    }

    public static String getPassword() {
        return password;
    }
}

4、 FtpUtil工具类

import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.ftp.Ftp;
import cn.hutool.extra.ftp.FtpMode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPFile;

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

/**
 * FTP服务工具类
 */
@Slf4j
public class FtpUtil {
    /**
     * 获取 FTPClient对象
     */
    private static Ftp getFTPClient() {
        try {
            if(StringUtils.isBlank(FtpConfig.getHost()) || FtpConfig.getPort() == null
                || StringUtils.isBlank(FtpConfig.getUserName()) || StringUtils.isBlank(FtpConfig.getPassword())) {
                throw new RuntimeException("ftp配置信息不能为空");
            }

            Ftp ftp = new Ftp(FtpConfig.getHost(),FtpConfig.getPort(),FtpConfig.getUserName(),FtpConfig.getPassword());
            //设置为被动模式,防止防火墙拦截
            ftp.setMode(FtpMode.Passive);
            return ftp;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取ftp客户端异常",e);
            throw new RuntimeException("获取ftp客户端异常:"+e.getMessage());
        }
    }

    /**
     * 下载ftp服务器上的文件到本地
     * @param remoteFile    ftp上的文件路径
     * @param localFile     输出的目录,使用服务端的文件名
     */
    public static void download(String remoteFile, String localPath) {
        if(StringUtils.isBlank(remoteFile) || StringUtils.isBlank(localPath)) {
            return;
        }

        Ftp ftp = getFTPClient();
        try {
            if(!FileUtil.exist(localPath)){
                FileUtil.mkdir(localPath);
            }    

            File lFile = FileUtil.file(localPath);
            ftp.download(remoteFile, lFile);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("FTP文件下载异常",e);
        } finally {
            //关闭连接
            try {
                if(ftp != null)  ftp.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 本地文件上传到ftp服务器上
     * @param remoteDir 上传的ftp目录
     * @param remoteFileName  保存到ftp服务器上的名称
     * @param localFile 本地文件全名称
     */
    public static boolean upload(String remoteDir, String remoteFileName, String localFile) {
        if(StringUtils.isBlank(remoteDir) || StringUtils.isBlank(remoteFileName) || StringUtils.isBlank(localFile)) {
            return false;
        }
        Ftp ftp = getFTPClient();
        try {
            File lFile = FileUtil.file(localFile);
            if(!lFile.exists()) {
                log.error("本地文件不存在");
                return false;
            }

            if(StringUtils.isBlank(remoteFileName)) {
                return ftp.upload(remoteDir, lFile);
            } else {
                return ftp.upload(remoteDir, remoteFileName, lFile);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("文件上传FTP异常",e);
            return false;
        } finally {
            //关闭连接
            try {
                if(ftp != null)  ftp.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 删除FTP服务器中的文件
     * @param remoteFile    ftp上的文件路径
     */
    public static boolean delFile(String remoteFile) {
        if(StringUtils.isBlank(remoteFile)) {
            return false;
        }

        Ftp ftp = getFTPClient();
        try {
            return ftp.delFile(remoteFile);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("删除FTP服务器中的文件异常",e);
            return false;
        } finally {
            //关闭连接
            try {
                if(ftp != null)  ftp.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 遍历某个目录下所有文件,不会递归遍历
     * @param path    目录
     */
    public static List<String> listFile(String path) {
        List<String> listFile = new ArrayList<>();
        Ftp ftp = getFTPClient();
        try {
            FTPFile[] ftpFiles = ftp.lsFiles(path);
            for (int i = 0; i < ftpFiles.length; i++) {
                FTPFile ftpFile = ftpFiles[i];
                if(ftpFile.isFile()){
                    listFile.add(ftpFile.getName());
                }
            }
            return listFile;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("遍历某个目录下所有文件异常",e);
            return null;
        } finally {
            //关闭连接
            try {
                if(ftp != null)  ftp.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

5、测试 

@RestController
@RequestMapping("/test")
public class TestController {
 
	
	@RequestMapping(value = "ftpTest", method = RequestMethod.GET)
	public void ftpTest() {
		//上传文件到ftp
		FtpUtil.upload("opt/upload","APP_RELATION.sql", "F:/APP_RELATION.sql");

		//下载远程文件
		FtpUtil.download("opt/upload/APP_RELATION.sql", "D:/");

		//删除远程文件
		FtpUtil.delFile("opt/upload/APP_RELATION.sql");
	}
 
}

总结:

上传的时候碰到一个问题,就是本地开启防火墙时,上传的文件大小是0kb,必须要关了防火墙才正常,后来FTP模式设置为“被动模式”解决。

//设置为被动模式,防止防火墙拦截
ftp.setMode(FtpMode.Passive);

主动模式(Active Mode):

  • 工作原理:客户端在本地打开一个非特权端口(通常大于1023),并通过这个端口发送PORT命令给服务器,告诉服务器客户端用于数据传输的端口号。然后,服务器使用其20端口(数据端口)主动连接到客户端指定的端口进行数据传输。
  • 安全性:由于服务器需要主动连接到客户端的端口,这可能引发一些安全问题,特别是当客户端位于防火墙或NAT设备后面时。
  • 适用场景:适用于客户端位于可以接受入站连接的网络环境,且没有防火墙或NAT设备限制的场景。

被动模式(Passive Mode): 

  • 工作原理:客户端发送PASV命令给服务器,服务器在本地打开一个端口(通常是高位的非特权端口),并通过PASV命令的响应告诉客户端这个端口号。然后,客户端主动连接到服务器指定的这个端口进行数据传输。
  • 安全性:由于客户端主动连接到服务器,这种模式更适合于客户端位于防火墙或NAT设备后面的场景,因为这些设备通常允许出站连接但限制入站连接。
  • 适用场景: 特别适用于网络环境不稳定、存在防火墙或NAT设备的场景。

http://www.kler.cn/a/323845.html

相关文章:

  • 什么是PostgreSQL,有什么特点
  • 【Linux:epoll】
  • T265相机双目鱼眼+imu联合标定(全记录)
  • K8S containerd拉取harbor镜像
  • 五、函数封装及调用、参数及返回值、作用域、匿名函数、立即执行函数
  • 《基于Oracle的SQL优化》读书笔记
  • 不将“旧”,换新家电的门槛又被TCL拉低了
  • 探索未来IT技术的浩瀚星河:一场跨越时代的数字盛宴
  • docker笔记_数据卷、挂载
  • 【STM32】RTT-Studio中HAL库开发教程七:IIC通信--EEPROM存储器FM24C04
  • Labview helper
  • 用最容易理解的方法,实现LRU、LFU算法
  • 代码随想录训练营第45天|编辑距离
  • 微前端框架之乾坤【qiankun】(一)
  • 使用SSE流式输出(Javaweb前后端实战)
  • 测试用例的进阶二
  • 速盾:视频开cdn合适还是视频点播合适?
  • cv2.waitkey(30) 按键盘无效
  • 快速排序(plus)与单调栈道,力扣912.排序数组​​​​​​​力扣215.数组中的第k大个元素力扣17.14最小的k个数单调栈力扣.柱状图中最大的矩形
  • OpenHarmony标准系统上实现对rk系列芯片NPU的支持(npu使用)
  • LORA DASH -一种更高效的微调方式
  • python医疗机器人手术
  • html TAB切换按钮变色、自动生成table--使用函数优化结构
  • opencv:实现图像的自动裁剪与优化
  • Python中的机器学习:从入门到实战
  • GO入门核心基础