Ftp下载文件超时处理
问题描述:
使用apache 开源库:commons-net 里的ftp进行文件下载,下载过程中发现由于网络拥挤或者是文件太大导致程序假死,不继续执行(实际上文件下载成功)
问题查找:
1、测试下载小文件没有问题
2、直接使用ftp命令下载(文件下载正常,但是没接收到返回码226)
3、文件实际下载成功(使用md5sum 校验文件是正常无损坏)
4、查看ftp服务器日志(vsftp.log)自己的服务器,如果是外部提供是无法查询的
ftp服务器端有正常返回,只是客户端没接收到
原因:
- FTPClient.listFiles()或者FTPClient.retrieveFile()方法时,就停止在那里,什么反应都没有,出现假死状态
- 连接FTP服务器,长时间进行数据操作时,超时自动断开
listFiles函数没反应可以下面方法(被动模式),这个方法的意思就是每次数据连接之前,ftp client告诉ftp server开通一个端口来传输数据
ftpClient.enterLocalPassiveMode();//不加这个无法加载文件列表
客户端断开连接添加keepAlive函数保持连接
ftpClient.login(username, password);
ftpClient.setControlKeepAliveTimeout(30);//用于设置传输控制命令的 Socket 的 alive 状态,注意单位为 s。
ftpClient.setControlKeepAliveReplyTimeout(3000);
retrieveFile()函数源码分析:
public boolean retrieveFile(String remote, OutputStream local)
throws IOException
{
InputStream input;
Socket socket;
if ((socket = _openDataConnection_(FTPCommand.RETR, remote)) == null)
return false;
input = new BufferedInputStream(socket.getInputStream(),
getBufferSize());
if (__fileType == ASCII_FILE_TYPE)
input = new FromNetASCIIInputStream(input);
CSL csl = null;
//使用setControlKeepAliveTimeout函数就是作用于这块,保持客户端和服务器的连接
if (__controlKeepAliveTimeout > 0) {
csl = new CSL(this, __controlKeepAliveTimeout, __controlKeepAliveReplyTimeout);
}
// Treat everything else as binary for now
try
{
Util.copyStream(input, local, getBufferSize(),
CopyStreamEvent.UNKNOWN_STREAM_SIZE, __mergeListeners(csl),
false);
} finally {
Util.closeQuietly(socket);
}
// Get the transfer response
boolean ok = completePendingCommand();
if (csl != null) {
csl.cleanUp(); // fetch any outstanding keepalive replies
}
return ok;
}
通过上述函数的添加解决大文件下载超时没正常返回226出现的假死情况
完整的连接ftp代码:
public static FTPClient createFTPClient(String ip, Integer port, String username, String password, String workDir)
throws SocketException, IOException {
FTPClient ftpClient = new FTPClient();
ftpClient.setDefaultTimeout(30 * 60 * 1000);
ftpClient.setConnectTimeout(30 * 60 * 1000);
ftpClient.setDataTimeout(30 * 60 * 1000);
ftpClient.connect(ip, port == null ? 21 : port);
// socket连接,设置socket连接超时时间(单位:ms)
ftpClient.setSoTimeout(30 * 60 * 1000);
ftpClient.enterLocalPassiveMode();//不加这个无法加载文件列表
ftpClient.login(username, password);
ftpClient.setControlKeepAliveTimeout(30);//用于设置传输控制命令的 Socket 的 alive 状态,注意单位为 s。
ftpClient.setControlKeepAliveReplyTimeout(3000);
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
int reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect(); // 如果返回状态不再 200 ~ 300 则认为连接失败
throw new RuntimeException("FTP链接失败");
}
if (workDir != null && !"".equals(workDir)) {
ftpClient.changeWorkingDirectory(workDir);
}
return ftpClient;
}
更多参数设置参考地址:https://www.cnblogs.com/dasusu/p/10006899.html
原文作者:zhuzi121121
原文地址: https://blog.csdn.net/zhuzi121121/article/details/111881277
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/zhuzi121121/article/details/111881277
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
相关文章