背景
正常情况下,我们都是把上传的文件保存到Java服务运行的服务器上。前段时间根据公司正式环境上的情况,必须要把文件做成跨服务器存储,经过考虑,最终采用FTP工具存储文件。
因为保存的文件并不是客户使用的文件,而是给运维人员使用的,所以这里并不需要考虑太多,直接写个简单的功能实现就好了。
正文
FTP服务站点怎么建,网上很多教程,不做赘述。本文只记录碰到的坑。
我是在window下开发,FTP服务端是window操作系统,开发阶段测试也在window下debug进行,正式环境下Java服务运行在linux上,采用docker部署。
在开发时一切正常,可是部署到服务器上,没有报出任何异常,但是ftp.storeFile()返回false。
依赖
查阅不少资料,很多人找不到jar包,甚至到网上求博主私信jar包,我不太理解为什么找不到,这里直接maven引入依赖就行了。
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
</dependency>
实现代码
public static boolean storeFile(String url,
int port,
String userName,
String password,
String storePath,
String fileName,
InputStream is) {
boolean result = false;
FTPClient ftp = new FTPClient();
try {
ftp.connect(url, port);
ftp.login(userName, password);
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
ftp.disconnect();
return result;
}
ftp.setControlEncoding("UTF-8");
ftp.enterLocalPassiveMode();
ftp.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
ftp.changeWorkingDirectory(storePath);
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
ftp.setBufferSize(3072);
fileName = new String(fileName.getBytes("GBK"), "iso-8859-1");
result = ftp.storeFile(fileName, is);
is.close();
ftp.logout();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != is) {
is.close();
}
if (ftp.isConnected()) {
ftp.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
重点在下面这两句:
ftp.enterLocalPassiveMode();// 被动模式
ftp.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);//设置传输方式为流方式
主动模式和被动模式
- PORT主动模式:ftp.enterLocalActiveMode();
在这个模式下,客户端通过服务端的默认端口与服务端连接。在使用时客户端会随机开发一个端口发送PORT命令道服务端,告诉服务端客户端采用了主动模式和开放的端口。服务端收到客户端的PORT命令后,与客户端连接发送数据。 - PASV被动模式:ftp.enterLocalPassiveMode();
在这个模式下,客户端发送的命令为PASV,此时是服务端开放端口给客户端连接,对于客户端而言是被动连接上服务端(客户端:我很被动,因为你服务端不告诉我端口,请问我要怎么连接?),开始数据传输。
在正式环境里面,服务器的防火墙基本都是开的,需要什么端口在开放什么端口,如果没有设置被动模式传输数据,那客户端恐怕一辈子都连不上服务端,这导致的结果就是文件传输请求成功了,但是文件没有传过去,返回false。
这也就是为什么服务器上没有上传的文件了。
至于为什么不会报错,我跟了一下源码,大概意思就是针对文件传输结果一个返回码的问题。
看上图,返回结果就是true或者false,并无报错。上面的注释大概意思就是请求会返回一个响应码,2开头为true,3开头就是false。
最后附上调用方法:
MultipartFile file = ((MultipartHttpServletRequest) request).getFile("file");
if (!file.isEmpty()) {
try {
InputStream inputStream = file.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
boolean res = FTPUtils.storeFile("127.0.0.1", "21", userName, password, "//", file.getOriginalFilename(), inputStream);
if (!res) {
msg = "FTP发生异常---->>>>文件上传失败";
return new ResponseDto<>(RespCode.ERROR.getId(), msg, null);
}
本文END。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)