Java Apache FTPClient在';快下载了

Java Apache FTPClient在';快下载了,java,ftp,apache-commons-net,Java,Ftp,Apache Commons Net,Apache的FTPClient无法下载完全由FileZilla下载的文件 基本上,在成功登录和登录后,我要做的是下载一个特定的文件: FTPClient client = new FTPClient(); client.setDataTimeout(20000); client.setConnectTimeout(20000); client.setBufferSize(65536); //... client.connect(host); client.login(user, pswd);

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>
java.net.SocketTimeoutException:读取超时
位于java.net.SocketInputStream.socketRead0(本机方法)
位于java.net.SocketInputStream.socketRead(未知源)
位于java.net.SocketInputStream.read(未知源)
位于java.net.SocketInputStream.read(未知源)
位于java.io.FilterInputStream.read(未知源)
位于java.io.BufferedInputStream.fill(未知源)
位于java.io.BufferedInputStream.read1(未知源)
位于java.io.BufferedInputStream.read(未知源)
位于java.io.FilterInputStream.read(未知源)
在
似乎没有防火墙,但当互联网连接速度更好时,下载成功(可能会出现某种超时)。我认为问题在于连接,但问题是FileZilla成功下载了相同的文件

因此,我可以这样重新表述我的问题:如何使我的
FTPClient
在下载文件时表现得像FileZilla。可能有一些复杂的ping逻辑重试,我不知道

Commons-Net:Commons-Net-3.6


FTP服务器:CentOS 5.8上的proftpd-1.3.3g-6.el5(默认配置)不支持通过TLS的FTP。

似乎是由以下行定义的数据超时引起的:

client.setDataTimeout(20000);
根据JavaDoc:

设置从数据连接读取时要使用的超时(以毫秒为单位)。此超时将在打开数据连接后立即设置,前提是该值为≥ 0

注意:在建立活动的本地数据连接时调用accept()时,也会应用超时

Parameters:timeout—打开数据连接套接字时使用的默认超时(以毫秒为单位)。值0表示无限超时


您是否可以尝试将此值设置为0(在此上下文中表示无限)?

我不知道这种现象的实际原因是什么(文件最后一块超时),但我已经向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);
    }
}
InputStream in=new BufferedInputStream(client.retrieveFileStream(ftpFilePath),16384);
// ...
字节[]缓冲区=新字节[8192];
长totalRead=0;
对于(int resumeTry=0;resumeTry 0){
//...
totalRead+=rd;
}
打破
}捕获(SocketTimeoutException ex){
//省略异常处理
in.close();
client.abort();
client.connect(…);
client.login(…);
客户端.setFileType(FTPClient.BINARY\u文件类型);
client.enterLocalPassiveMode();
client.setRestartOffset(totalRead);
in=client.retrieveFileStream(…);
if(in==null){
//FTP服务器不支持REST FTP查询
掷骰子;
}
in=新的BufferedInputStream(in,16384);
}
}

谢谢你的回复,我会尽力让你知道这没有帮助,也不应该有,因为这是一个
读取
操作的超时时间,必须在20秒内成功。抱歉,我的检查错误,我在某个不正确的位置删除了它,需要再次检查。是的,现在它永远挂起100%左右