首页 > 编程语言 >Java实现FTP文件上传和下载

Java实现FTP文件上传和下载

时间:2023-12-04 15:34:45浏览次数:30  
标签:FTP Java 文件 端口 服务器 上传 ftpClient

目录
一、背景
二、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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
三、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);//毫秒
//连接FTP
ftpClient.connect(hostName, port);
//更加账户密码登录服务
ftpClient.login(userName, password);
//被动模式(需要设置在连接之后,尤其linux环境)
ftpClient.enterLocalPassiveMode();
}

/**
* FTP上传文件
*
* @param remoteUploadDirectory 要上传的目录(FTP服务器上的目录)
* @param localUploadFilePathName 本地上传文件的完整路径(本地路径)
* @return
*/
public Pair<Boolean, String> uploadFile(String remoteUploadDirectory, String localUploadFilePathName) {
FileInputStream fis = null;
try {
// 如果不能进入dir下,说明此目录不存在!
System.out.println("FTP响应码:"+ftpClient.getReplyCode());
System.out.println("FTP响应信息:"+ftpClient.getReplyString());
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);
//设置文件类型(二进制)
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);
log.info("上传文件响应信息:{}", ftpClient.getReplyString());
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();
}
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  注意构造方法中的调用,FTP协议有两种工作方式:

// 被动模式(需要设置在连接之后,尤其linux环境)
ftpClient.enterLocalPassiveMode();
1
2
  如果是windows环境上传下载没啥问题,如果是linux环境,可能端口未开放就需要我们使用这个被动模式,而且是登录之后,不然你调用 listFiles() 方法可能就是返回null了。

  如果你是要设置编码的话,你需要在你连接,登录之前进行设置。不然就是无效,FTP服务器默认的编码是 ISO-8859-1 。所以你上传和下载时,不管是文件目录,或者文件名,或者文件的编码都要进行相应的统一转换,我这里就没有改服务器上编码格式了。

//被动模式(需要设置在连接之前)
ftpClient.setControlEncoding("UTF-8");
1
2
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
1
2
3
4
5
6
本文登录后的文件列表:


4.2、FTP文件上传
@Test
public 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",);
log.info("上传返回结果:{}", pair);
apacheFtpClient.close();
}
1
2
3
4
5
6
7
运行结果:

17:16:55.830 [main] INFO com.alian.ftp.utils.ApacheFtpClient - 上传文件响应码:226
17:16:55.835 [main] INFO com.alian.ftp.service.TestApacheFtpService - 上传返回结果:(true,上传成功)
1
2
登录FTP服务器上查看文件如下:


4.3、FTP文件下载
@Test
public 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();
}
1
2
3
4
5
6
7
运行结果:

17:20:37.126 [main] INFO com.alian.ftp.utils.ApacheFtpClient - 下载文件响应码:226
17:20:37.130 [main] INFO com.alian.ftp.service.TestApacheFtpService - 下载返回结果:(true,下载成功)
1
2
进入到我们本地下载的目录,结果如下:

————————————————
版权声明:本文为CSDN博主「嘉禾嘉宁papa」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Alian_1223/article/details/121315158

标签:FTP,Java,文件,端口,服务器,上传,ftpClient
From: https://www.cnblogs.com/roak/p/17875051.html

相关文章

  • Java_01
    <?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--参数占位符#{}:执行SQL时,会将#{}占位符替换为?,将来自......
  • SpringBoot文件上传下载
    1、单文件上传这里的enctype的类型是mulitpart/form-data两种形式的提交,一种是以form表单的形式,一个是ajax的形式<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>上传文件</title><scriptsrc="https://cdn.bo......
  • 记录java中多字段分组
    packagecn.mw;importjava.util.*;importjava.util.stream.Collectors;importjava.util.stream.Stream;classNetworkConnection{privateStringsrcIp;privateStringdstIp;privateintsrcPort;privateintdstPort;publicNetworkCon......
  • Java开发者的Python快速实战指南:探索向量数据库之图像相似搜索-文字版
    首先,我要向大家道个歉。原本我计划今天向大家展示如何将图片和视频等形式转换为向量并存储在向量数据库中,但是当我查看文档时才发现,腾讯的向量数据库尚未完全开发完成。因此,今天我将用文本形式来演示相似图片搜索。如果您对腾讯的产品动态不太了解,可以查看官方网址:https://cloud.t......
  • 【Java 进阶篇】Java Request 获取请求体数据详解
    在JavaWeb开发中,获取HTTP请求的请求体数据是一项常见任务。HTTP请求的请求体通常包含了客户端提交的数据,例如表单数据、JSON、XML等。在Java中,可以使用HttpServletRequest对象来获取HTTP请求的请求体数据。本文将详细解释如何使用Java获取HTTP请求的请求体数据,并提供示例代码。HTT......
  • Java异常处理
    异常处理是Java编程中的一个核心概念,它提供了一种强大的方法来处理运行时错误,使我们的程序更加健壮。异常是程序运行过程中发生的不正常情况,它打断了正常的指令流。本文将介绍Java中的异常处理机制,包括异常的类型、如何捕获和处理异常,以及自定义异常。异常类型在Java中,所有的异常都......
  • java中http请求中sessionID的生成方式
    java中http请求中sessionID的生成方式今天的笔记是为了搞清楚4个问题,搞清楚这四个问题,那么我工作上的困难也就解决了。1).sessionId是在什么地方生成的?2).sessionId的生产规则是怎么样的?3).sessionId存储在哪里?4).sessionId可以如何获取?它是在容器里面生成的,spingBoo......
  • Java 连接MySql数据库配置
    用navicat连接Mysql1.点击连接,选择Mysql2.输入连接名称,密码,安装Mysql时输入的密码,本人默认123456,好记3.点击测试连接出现上面这种情况是Mysql服务没有开启解决方案:任务管理器 ------服务------找到mysql服务----右键开始启动服务之后,打开我们的navicat,再次测试连接,点击确定打开本......
  • Java零基础-if条件语句
    前言条件语句是编程语言中最基础也是最常用的语句之一,对于初学者来说,掌握好条件语句是学习编程的第一步。本文将以Java开发语言为例,详细介绍Java中的if条件语句及其应用场景。摘要本文主要包含以下内容:Java中的if条件语句的概念和语法格式if条件语句的源代码解析if条件语句......
  • Java泛型的定于与使用
    Java泛型的定于与使用泛型也叫泛类型。Java中可以声明泛型的地方。泛型的分类:泛型类:在类的定义时,声明泛型泛型接口:在接口的定义时,声明泛型泛型方法:在类的方法上声明泛型一、泛型类1、语法className<T1,T2,...,Tn>{//}/**T代表一个Java类,在类上声明......