发布于 

FTPS服务器搭建加FTPS进行文件上传

搭建FTPS服务器

获取vsftpd最新的docker镜像

1
docker pull fauria/vsftpd

启动镜像

1
2
3
4
5
6
7
8
9
docker run -d -p 21:21 -p 20:20 -p 21100-21110:21100-21110 \
-v /home/dispatch/test/root:/home/vsftpd/test \
-e FTP_USER=test \
-e FTP_PASS=test \
-e PASV_ADDRESS=服务器对外ip \
-e PASV_MIN_PORT=21100 \
-e PASV_MAX_PORT=21110 \
--name vsftpd \
--restart=always fauria/vsftpd

注意启动挂在文件目录时最下面一层是和用户名一致的

生成SSl证书文件

1
2
# 检查是否安装证书生成工具openssl
rpm -qa | grep openssl

没有安装的安装一下

1
yum install mod_ssl openssl

生成SSL证书文件

1
2
3
4
5
6
7
8
9
#OpenSSL指令注释:
#req #是 X.509 Certificate Signing Request (CSR,证书签名请求)管理的一個命令。
#x509 #X.509 证书资料管理。
#days #定义证书的有效日期。
#newkey #指定证书秘钥处理器。
#keyout #設定秘钥存储文件。
#out #設定证书存储文件,注意证书和秘钥都储存在一個相同的文件
openssl req -new -x509 -nodes -out vsftpd.pem -keyout vsftpd.pem -days 3560
Generating a 2048 bit RSA private key

需要填写所在国家,城市之类的,看着填就行

进行FTPS的配置

由于我这边是安装到docker中的,所以需要将秘钥文件移动到容器中

1
docker cp ./vsftpd.pem {容器id}:/etc/vspdfd/

进入容器到配置目录下

1
2
3
4
5
6
7
8
# 进入容器
docker exec -it {容器id} /bin/bash

# 进入配置目录
cd /etc/vsftpd/

# 编辑配置文件
vi vsftpd.conf

添加配置

1
2
3
4
5
rsa_cert_file=/etc/vsftpd/vsftpd.pem
rsa_private_key_file=/etc/vsftpd/vsftpd.pem
ssl_enable=YES
#不重用SSL会话,安全配置项(不配置会导致代码连接失败)
require_ssl_reuse=NO

配置最好是放在配置文件最上方,不然可能导致启动失败,循环重启

退出容器并且重启

工具连接测试

这里我使用的工具是cuteFTP

成功连接

java代码FTPS文件上传工具

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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ftp.Ftp;
import cn.hutool.extra.ftp.FtpException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.net.ftp.FTPSClient;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/**
* @author cjb
* @date 2022-04-08 14:15
* @description ftp 文件上传工具
*/
@Slf4j
public class FtpUtil {

/** 本地字符编码 */
private static String LOCAL_CHARSET = "GBK";

// FTP协议文件名编码为iso-8859-1
private static String SERVER_CHARSET = "ISO-8859-1";

/**
* 操作完成后是否返回原目录
*/
private static boolean backToPwd = true;


/**
* 创建ftps连接对象
* @param host
* @param port
* @param user
* @param password
* @return
*/
public static FTPSClient createFTPSConnection(String host, int port, String user, String password){
FTPSClient ftpsClient = new FTPSClient();
try {
ftpsClient.connect(host, port);
//FTP的用户名和密码
ftpsClient.login(user,password);
// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
// if (FTPReply.isPositiveCompletion(ftpsClient.sendCommand(
// "OPTS UTF8", "ON"))) {
// LOCAL_CHARSET = "UTF-8";
// }
ftpsClient.setFileType(FTP.BINARY_FILE_TYPE);
ftpsClient.setControlEncoding(LOCAL_CHARSET);
ftpsClient.execPBSZ(0);
ftpsClient.execPROT("P");
ftpsClient.enterLocalPassiveMode();
} catch (IOException e) {
log.error("ftps连接创建失败");
e.printStackTrace();
return null;
}
return ftpsClient;
}

/**
* 上传文件
* @param destPath 上传路径
* @param fileName 上传文件名称
* @param fileStream 文件流
* @param client 连接对象
* @return
* @throws IORuntimeException
*/
public static boolean upload(String destPath, String fileName, InputStream fileStream,FTPSClient client) throws IORuntimeException {
try {
client.setFileType(FTPClient.BINARY_FILE_TYPE);
} catch (IOException e) {
throw new IORuntimeException(e);
}

String pwd = null;
if (FtpUtil.backToPwd) {
pwd = FtpUtil.pwd(client);
}

if (StrUtil.isNotBlank(destPath)) {
FtpUtil.mkDirs(client,destPath);
if (false == FtpUtil.isDir(client,destPath)) {
throw new FtpException("Change dir to [{}] error, maybe dir not exist!", destPath);
}
}

try {
return client.storeFile(fileName, fileStream);
} catch (IOException e) {
throw new IORuntimeException(e);
} finally {
if (FtpUtil.backToPwd) {
FtpUtil.cd(client,pwd);
}
}
}

/**
* 进入目录
* @param client 连接对象
* @param directory 目录
* @return
*/
public static boolean cd(FTPSClient client,String directory) {
if (StrUtil.isBlank(directory)) {
// 当前目录
return true;
}

try {
return client.changeWorkingDirectory(directory);
} catch (IOException e) {
throw new IORuntimeException(e);
}
}

/**
* 创建目录
* @param client 连接对象
* @param dir 文件路径
*/
public static void mkDirs(FTPSClient client,String dir) {
final String[] dirs = StrUtil.trim(dir).split("[\\\\/]+");

final String now = FtpUtil.pwd(client);
if (dirs.length > 0 && StrUtil.isEmpty(dirs[0])) {
//首位为空,表示以/开头
FtpUtil.cd(client,StrUtil.SLASH);
}
for (String s : dirs) {
if (StrUtil.isNotEmpty(s)) {
boolean exist = true;
try {
if (false == FtpUtil.cd(client,s)) {
exist = false;
}
} catch (FtpException e) {
exist = false;
}
if (false == exist) {
//目录不存在时创建
FtpUtil.mkdir(client,s);
FtpUtil.cd(client,s);
}
}
}
// 切换回工作目录
FtpUtil.cd(client,now);
}

/**
* 创建目录
* @param client 连接对象
* @param dir 文件夹名称
* @return
* @throws IORuntimeException
*/
public static boolean mkdir(FTPSClient client,String dir) throws IORuntimeException {
try {
return client.makeDirectory(dir);
} catch (IOException e) {
throw new IORuntimeException(e);
}
}

/**
* 显示当前目录
* @param client 连接对象
* @return
*/
public static String pwd(FTPSClient client) {
try {
return client.printWorkingDirectory();
} catch (IOException e) {
throw new IORuntimeException(e);
}
}

/**
* 判断给定路径是否为目录
*
* @param dir 被判断的路径
* @return 是否为目录
* @since 5.7.5
*/
public static boolean isDir(FTPSClient client,String dir) {
return FtpUtil.cd(client,dir);
}

}

本站由 @binvv 使用 Stellar 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。