Apache的FTPClient无法下载FileZilla完美下载的文件。
基本上,在成功登录和列表之后,我要做的是下载一个特定的文件:
FTPClient client = new FTPClient();
client.setDataTimeout(20000);
client.setConnectTimeout(20000);
client.setBufferSize(65536);
//...
client.connect(host);
client.login(user, pswd);
// response validation
client.enterLocalPassiveMode();
// some listings with validations
InputStream in = new BufferedInputStream(client.retrieveFileStream(ftpFilePath), 16384);
// ...
byte[] buffer = new byte[8192];
while ((rd = in.read(buffer)) > 0) {
// .. reading the file and updating download progress最后一行可以很容易地替换为FTPClient的文件下载,结果几乎相同,但是我们无法跟踪下载进度:
client.setControlKeepAliveTimeout(30);
client.retrieveFile(ftpFilePath, new org.apache.commons.io.output.NullOutputStream());作为所有这些操作的结果,我可以看到文件正在下载,直到非常接近100%的内容,然后出现异常:
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.io.FilterInputStream.read(Unknown Source)
at java.io.BufferedInputStream.fill(Unknown Source)
at java.io.BufferedInputStream.read1(Unknown Source)
at java.io.BufferedInputStream.read(Unknown Source)
at java.io.FilterInputStream.read(Unknown Source)
at <my code from here on>似乎没有防火墙,但当互联网连接速度更快时,下载就会接续(可能会有某种超时)。我认为问题在于连接,但问题是FileZilla成功地下载了相同的文件。
因此,我可以这样重新表述我的问题:如何使我的FTPClient在下载文件时表现得像FileZilla。也许,在ping逻辑上有一些我不知道的复杂的重试。
公地网:公地-网-3.6
FTP服务器: proftpd-1.3.3g-6.el5在CentOS 5.8上具有默认配置,不支持TLS上的FTP。
发布于 2018-01-05 16:25:29
我不知道造成这种现象的实际原因是什么(在文件的最后一块上超时),但我已经与Wireshark检查了FileZilla下载文件是做什么的,发现同样的超时也存在同样的问题,它正在重新连接到服务器,并发送REST FTP查询重新启动这个特定文件的下载,从文件中止时开始,即只下载最后一块文件。
因此,解决方案是在下载过程中添加某种重试逻辑,以便这段代码:
InputStream in = new BufferedInputStream(client.retrieveFileStream(ftpFilePath), 16384);
// ...
byte[] buffer = new byte[8192];
while ((rd = in.read(buffer)) > 0) {变成这样:
InputStream in = new BufferedInputStream(client.retrieveFileStream(ftpFilePath), 16384);
// ...
byte[] buffer = new byte[8192];
long totalRead = 0;
for (int resumeTry = 0; resumeTry <= RESUME_TRIES; ++resumeTry) {
try {
while ((rd = in.read(buffer)) > 0) {
//...
totalRead += rd;
}
break;
} catch (SocketTimeoutException ex) {
// omitting exception handling
in.close();
client.abort();
client.connect(...);
client.login(...);
client.setFileType(FTPClient.BINARY_FILE_TYPE);
client.enterLocalPassiveMode();
client.setRestartOffset(totalRead);
in = client.retrieveFileStream(...);
if (in == null) {
// the FTP server doesn't support REST FTP query
throw ex;
}
in = new BufferedInputStream(in, 16384);
}
}发布于 2018-01-04 11:19:29
它似乎是由在下面一行中定义的数据超时引起的:
client.setDataTimeout(20000);根据JavaDoc的说法:
设置从数据连接读取时要使用的超时(毫秒)。此超时将在打开数据连接后立即设置,条件是该值为≥0。 注意:在建立活动本地数据连接时,调用accept()时也会应用超时。 参数:超时值-打开数据连接套接字时使用的默认超时(毫秒)。值0表示无限超时。
您是否可以尝试将此值设置为0(在此上下文中这意味着无限)?
https://stackoverflow.com/questions/48093928
复制相似问题