目录

  • 一、背景
  • 二、maven依赖
  • 三、FTP工具类
    • 3.1、主动模式(PORT)
    • 3.2、被动模式(PASV)
  • 四、验证
    • 4.1、dos下操作FTP
    • 4.2、FTP文件上传
    • 4.3、FTP文件下载

一、背景

  我在之前的文章(Java实现文件上传和下载)里讲过非FTP文件的上传和下载,今天我们来讲一下FTP文件上传和下载,本文测试过程中Spring Boot 版本为2.5.2,commons-net 版本为3.8.0,JDK环境为 1.8。本文是在window环境下完成的,因为本机环境的复杂性,是把本机的防火墙关闭了的(不然dos登录后操作不了,或者上传下载超时)。

二、maven依赖

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.2</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.alian</groupId><artifactId>ftp</artifactId><version>0.0.1-SNAPSHOT</version><name>ftp</name><description>java实现FTP文件上传下载</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version></dependency><dependency><groupId>commons-net</groupId><artifactId>commons-net</artifactId><version>3.8.0</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.14</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>compile</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

三、FTP工具类

  本工具类中包含四个方法,实例化方法,上传文件,下载文件,及关闭连接方法。

ApacheFtpClient.java

package com.alian.ftp.utils;import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;import java.io.*;@Slf4j
public class ApacheFtpClient {private FTPClient ftpClient;/*** 实例化** @param hostName FTP服务器地址* @param port     FTP服务器端口* @param userName FTP登录账户* @param password FTP登录密码* @throws IOException*/public ApacheFtpClient(String hostName, int port, String userName, String password) throws IOException {ftpClient = new FTPClient();//设置传输命令的超时ftpClient.setDefaultTimeout(20000);//毫秒//设置两个服务连接超时时间ftpClient.setConnectTimeout(10000);//毫秒//被动模式下设置数据传输的超时时间ftpClient.setDataTimeout(15000);//毫秒//被动模式(需要设置在连接之前)ftpClient.enterLocalPassiveMode();//连接FTPftpClient.connect(hostName, port);//更加账户密码登录服务ftpClient.login(userName, password);}/*** FTP上传文件** @param remoteUploadDirectory   要上传的目录(FTP服务器上的目录)* @param localUploadFilePathName 本地上传文件的完整路径(本地路径)* @param encoding                编码* @return*/public Pair<Boolean, String> uploadFile(String remoteUploadDirectory, String localUploadFilePathName, String encoding) {FileInputStream fis = null;try {// 如果不能进入dir下,说明此目录不存在!if (!ftpClient.changeWorkingDirectory(remoteUploadDirectory)) {log.info("没有目录:{}", remoteUploadDirectory);if (!ftpClient.makeDirectory(remoteUploadDirectory)) {log.info("创建文件目录【{}】 失败!", remoteUploadDirectory);return Pair.of(false, "创建文件目录【" + remoteUploadDirectory + "】 失败");}}//进入文件目录ftpClient.changeWorkingDirectory(remoteUploadDirectory);//创建文件流fis = new FileInputStream(new File(localUploadFilePathName));//设置上传目录ftpClient.setBufferSize(1024);//设置编码(默认是ISO-8859-1)ftpClient.setControlEncoding(encoding);//设置文件类型(二进制)ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);//FTP服务器上最终的名字String uploadFileName = localUploadFilePathName.substring(localUploadFilePathName.lastIndexOf(File.separator) + 1);//文件上传boolean b = ftpClient.storeFile(uploadFileName, fis);int replyCode = ftpClient.getReplyCode();log.info("上传文件响应码:{}", replyCode);return Pair.of(b, b ? "上传成功" : "上传失败");} catch (Exception e) {log.error("FTP上传文件异常!:", e);return Pair.of(false, "上传文件异常");} finally {try {if (fis != null) {fis.close();}} catch (IOException e) {log.error("关闭流发生异常!", e);}}}/*** FTP文件下载** @param remoteDownloadDirectory 要下载的目录(FTP服务器目录)* @param localDirectory          本地下载文件路径* @param downloadFileName        下载的文件名* @return*/public Pair<Boolean, String> downloadFile(String remoteDownloadDirectory, String localDirectory, String downloadFileName) {OutputStream out = null;try {if (StringUtils.isBlank(downloadFileName)) {return Pair.of(false, "要下载的文件不能为空");}//工作目录切换到下载文件的目录下if (!ftpClient.changeWorkingDirectory(remoteDownloadDirectory)) {log.info("目录不存在:{}", remoteDownloadDirectory);return Pair.of(false, "目录不存在");}//获取目录下所有文件FTPFile[] files = ftpClient.listFiles();if (files.length < 1) {return Pair.of(false, "目录为空");}boolean fileExist = false;boolean downloadFlag = false;//遍历文件列表for (FTPFile ftpFile : files) {String localFile = localDirectory + File.separator + downloadFileName;//是否存在要下载的文件if (downloadFileName.equals(ftpFile.getName())) {fileExist = true;out = new FileOutputStream(localFile);//下载downloadFlag = ftpClient.retrieveFile(downloadFileName, out);int replyCode = ftpClient.getReplyCode();log.info("下载文件响应码:{}", replyCode);break;}}if (!fileExist) {return Pair.of(false, "FTP服务器上文件不存在");}return Pair.of(downloadFlag, downloadFlag ? "下载成功" : "下载失败");} catch (Exception e) {log.error("FTP下载文件异常!:", e);return Pair.of(false, "下载文件异常");} finally {try {if (out != null) {out.flush();out.close();}} catch (IOException e) {e.printStackTrace();}}}public void close() {try {if (ftpClient != null && ftpClient.isConnected()) {ftpClient.disconnect();}} catch (IOException e) {e.printStackTrace();}}}

  注意构造方法中的调用,FTP协议有两种工作方式:

 //被动模式(需要设置在连接之前)ftpClient.enterLocalPassiveMode();

3.1、主动模式(PORT)

  主动模式的FTP是指服务器主动连接客户端的数据端口。

  • FTP客户端随机开启一个大于1024的端口N向服务器的21号端口发起连接,同时开放N+1号端口进行监听,然后发送PORT命令到FTP服务器,告知是主动模式
  • FTP服务器给客户端的命令端口返回一个ACK的应答码
  • FTP客户端发出数据传输的指令
  • FTP服务器发起一个从它自己的数据端口(一般是20端口)到客户端先前指定的数据端口(N+1)的连接
  • FTP客户端返回一个ACK后,进行数据传输

3.2、被动模式(PASV)

  被动模式的FTP是指服务器被动地等待客户端连接自己的数据端口。

  • FTP客户端随机开启一个大于1024的端口N向服务器的21号端口发起连接,同时会开启N+1号端口。然后向服务器发送PASV命令,告知是被动模式
  • FTP服务器收到命令后,会开放一个大于1024的端口P进行监听,然后用PORT命令通知客户端,服务端的数据端口是P
  • FTP客户端发出数据传输的指令,会通过N+1号数据端口连接服务器的端口P
  • FTP服务器给客户端的数据端口返回一个ACK的应答码,然后在两个端口之间进行数据传输

四、验证

4.1、dos下操作FTP

  如果你是window环境下操作FTP,建议关闭防火墙操作。
输入命令:

#在cmd命令提示符下输入(ftp加FTP服务器地址)
ftp 192.168.0.151
#根据提示输入用户名
Alian
#根据提示输入登录密码
Alian@1223

本文登录后的文件列表:

4.2、FTP文件上传

    @Testpublic void upload() throws IOException {ApacheFtpClient apacheFtpClient = new ApacheFtpClient("192.168.0.151", 21, "Alian", "Alian@1223");Pair<Boolean, String> pair = apacheFtpClient.uploadFile("apacheFTP", "C:\\myFile\\CSDN\\result.png", "GBK");log.info("上传返回结果:{}", pair);apacheFtpClient.close();}

运行结果:

17:16:55.830 [main] INFO com.alian.ftp.utils.ApacheFtpClient - 上传文件响应码:226
17:16:55.835 [main] INFO com.alian.ftp.service.TestApacheFtpService - 上传返回结果:(true,上传成功)

登录FTP服务器上查看文件如下:

4.3、FTP文件下载

    @Testpublic void download() throws IOException {ApacheFtpClient apacheFtpClient = new ApacheFtpClient("192.168.0.151", 21, "Alian", "Alian@1223");Pair<Boolean, String> pair = apacheFtpClient.downloadFile("apacheFTP", "C:\\myFile\\download", "result.png");log.info("下载返回结果:{}", pair);apacheFtpClient.close();}

运行结果:

17:20:37.126 [main] INFO com.alian.ftp.utils.ApacheFtpClient - 下载文件响应码:226
17:20:37.130 [main] INFO com.alian.ftp.service.TestApacheFtpService - 下载返回结果:(true,下载成功)

进入到我们本地下载的目录,结果如下:

Java实现FTP文件上传和下载相关推荐

  1. java中ftp删除文件,Java 实现ftp 文件上传、下载和删除

    实现FTP相关功能 1.下载相应的jar包 commons-net-3.6.jar 2.代码实现 import java.io.File; import java.io.FileInputStream ...

  2. java里面的文件上传与下载

    java里面的文件上传与下载 文件的上传与下载主要用到两种方法: 1.方法一:commons-fileupload.jar commons-io.jar apache的commons-fileuplo ...

  3. Java如何进行文件上传与下载

    Java文件上传与下载 在项目开发中难免遇到这样的问题,对于我这种小白,那只能寻求度娘的帮助拉,各种搜索和看博客文章,当实际运行时....哎,痛苦. 今日分享一波,望你所用,烦闷去之. 文件上传 首先 ...

  4. java 中 FtpClient 实现 FTP 文件上传、下载

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 源代码大部分是网上找的,查来查去,找到几个可以用的例子,改来改去,揉合成现在这个样子. 一. jar ...

  5. java 文件下载漏洞,文件上传和下载漏洞

    一.文件下载漏洞 1.需要寻找文件下载的路径进行构造一般链接形式: download.php?path= down.php?file= data.php?file= download.php?file ...

  6. 【SpringBoot】:springboot整合FTP文件上传与下载功能

    导入依赖包 <dependency><groupId>commons-net</groupId><artifactId>commons-net</ ...

  7. Java实现ftp的上传、下载和删除

    前期准备 1. 搭建Ftp服务器 为了方便本地测试,一开始可以先在本地搭建Ftp服务器.搭建Ftp服务器的教程有很多,这里就不多讲了,下面是我用到的教程你们可以参考一下. 百度经验:Win10如何搭建 ...

  8. java web fileupload_javaweb 文件上传(fileupload) 下载

    1 文件上传 html中通过可以向服务器上传文件.不过后台需要手动解析请求,比较复杂,所以可以使用smartupload或apache的fileupload组件进行文件的上传.smartupload据 ...

  9. ftp文件上传和下载

    ftp参数实体 public class FTPParameter { private String host;private int port;private String user;private ...

  10. 使用API进行FTP文件上传和下载

    又有几天没发新贴了,刚才有点闲瑕,便随手写了一个使用FTP上传和下载文件的类. 类代码如下: Option Explicit'* *********************************** ...

最新文章

  1. SIP穿越NATFireWall解决方案
  2. I2C从驱动到应用(中篇)
  3. 2020年快手校招JAVA岗笔试第三题
  4. gentoo使用unicon支持中文
  5. mysql -- MAC下安装配置mysql
  6. 使用Azure DevOps持续集成GitHub项目
  7. mysql -b -e_MySQL 的B+树索引.
  8. 优雅的找出ArrayList中重复的元素
  9. freeCodeCamp:Diff Two Arrays
  10. 如何将android连接到pc,如何将Android屏幕镜像到PC
  11. C#教程第四课:循环控制语句
  12. [leetcode] 554. 砖墙
  13. 计算机打开共享网络连接打印机共享打印机,WIN7怎么连接共享打印机?如何设置和连接局域网共享打印机...
  14. 机器视觉基础知识汇总
  15. 工作3年进阿里,取得P7职位,需要怎样的技术能力?(面试题附答案)
  16. 小明一家人,如何在30秒内过桥
  17. 4个方法:提升用户活跃度
  18. 三菱PLC CCD控制ST程序 本PLC程序中CCD控制用的ST结构化语言,程序都有注释
  19. python爬取凤凰新闻网_python凤凰新闻数据分析(一)python爬虫数据爬取
  20. Python数据分析中数据预处理:编码将文字型数据转换为数值型

热门文章

  1. 计算机怎么格式化硬盘,电脑格式化硬盘 电脑格式化硬盘要怎么操作
  2. git commit 参数详解 --amend
  3. 谈谈JavaScript版本演进史及ES3、ES5区别和特性
  4. Python3+Scrapy实现网页爬虫
  5. 调和平均数的几何意义
  6. 【xinfanqie】熟知针式与喷墨打印机之间的区别
  7. (C++)整型数组A[n]中的元素调整为左右两部分,其中左边所有元素为奇数,右边所有元素为偶数。时间复杂度为O(n)。
  8. 关于微信双开后,王者荣耀默认只能打开微信主应用问题
  9. 压缩感知高斯测量矩阵matlab,基于压缩感知的测量矩阵研究
  10. android航拍效果,足不出户看遍大好河山!超震撼的航拍全景APP