问题描述:我端写了个rest接口,对方发送文件地址到该端口,然后我端去下载文件,ftp协议。但是一段时间后,大概几个小时,对方服务器就会宕机。也就是搞崩了。
解决思路:一直怀疑是ftp连接未关闭、或者文件流未关闭导致的。
所以写了一下代码:
public void download(ReqBody body) {
FTPClient ftp = null;
try {
String vendor = body.getVendor();
String localPath = config.getLocalpath() + "/" + vendor;
File localDir = new File(localPath);
if(!localDir.exists()){ //如果本地路径不存在,则创建
localDir.mkdirs();
}
String connectionStr = body.getConnectionString().replaceAll("ftp://", "");
String username = connectionStr.substring(0, connectionStr.indexOf(":"));
String password = connectionStr.substring(connectionStr.indexOf(":") + 1, connectionStr.lastIndexOf("@"));
String host = connectionStr.substring(connectionStr.lastIndexOf("@") + 1, connectionStr.lastIndexOf(":"));
int port = Integer.parseInt(connectionStr.substring(connectionStr.lastIndexOf(":") + 1));
String file = body.getFileList();
ftp = new FTPClient();
ftp.connect(host, port);
ftp.login(username, password);
ftp.enterLocalPassiveMode(); //默认是主动0 被动模式 ftp分布式采用
ftp.setRemoteVerificationEnabled(false); //取消主机验证
ftp.setControlEncoding("utf-8");
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);//二进制模式
int reply = ftp.getReplyCode();
if (FTPReply.isPositiveCompletion(reply)) {
logger.info("连接FTP服务端成功!" + reply);
File remoteFile = new File(file);
File localFile = new File(localDir, remoteFile.getName());
OutputStream os = new FileOutputStream(localFile);
ftp.changeWorkingDirectory(remoteFile.getParent());
logger.info("切换路径!" + remoteFile.getParent());
boolean b = ftp.retrieveFile(remoteFile.getName(), os);
if (b) {
logger.info("ftp文件下载成功:{}", file);
} else {
logger.error("ftp文件下载失败:{}", file);
}
os.close();
}else{
logger.error("连接FTP服务端被拒绝!" + reply);
return;
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp != null) {
try {
ftp.logout();
ftp.disconnect();
ftp = null;
} catch (IOException e) {
logger.error("关闭FTP连接失败{}", e.getMessage());
}
}
}
}可以看到代码里面:
io流都关闭了,ftp也登出断开连接了,但是还是崩。
然后查了些资料,有这么一个方法:
ftpClient.completePendingCommand();官方说法是:完成文件传输必须调用completependingcommand和检查它的返回值来验证成功。如果没有这样做,后续命令可能会意外地出错
简单来说:completePendingCommand()会一直在等FTP Server返回226 Transfer complete,但是FTP Server只有在接受到InputStream执行close方法时,才会返回。所以先要执行close方法
调用这个接口后,一定要手动close掉返回的InputStream,然后再调用completePendingCommand方法,若不是按照这个顺序,则会导致后面对FTPClient的操作都失败。
然后我在文件流关闭后,执行这个方法,但是还是崩。
于是我把ftpClient的logout和disconnect这段代码去掉。
不崩了。难道不能同时使用?
版权声明:本文为qqnbsp原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。