我正在使用 commons-net 中的 Java FTPClient 类从 ftp 服务器下载大文件。如果我检测到某些连接失败,我希望文件从某个偏移量重新开始下载,例如:我的客户端连接断开或我的服务器关闭连接。如果我在client.retrieveFile(filename, out)
下载文件时关闭客户端连接,我不会得到任何异常,程序只是冻结在那里而不下载或做任何事情。如何触发此事件?我看到了一个 FTPConnectionClosedException,但它只在服务器关闭我的连接时才被调用。
问问题
1314 次
2 回答
0
您可以保留某种序列 ID,它可以表示已下载了多少数据,并在您合法完成后将其设置为某个特殊值。
sequence=0;
try{
while(notDone){
n = client.retrieveFile(filename, out); //bytes read
sequence =+ n;
}finally{
if(sequence != SPECIAL_VALUE){
throw new customException();
}
}
最终,您的代码将执行 finally 块,您可以决定如何处理它。或者,如果您想要更多解决方案,您可以通过测量上次更新fail fast
时间来使用超时。sequence
希望这可以帮助!
于 2013-07-26T11:10:33.030 回答
0
您可以ftpClient.getState()
在下载过程中定期调用并行 therad。如果连接消失,它会抛出 SocketTimeoutException。此外,以前您需要通过以下方式设置超时(例如五秒)ftp.setControlKeepAliveTimeout(5)
这是示例:
ftpClient.setControlKeepAliveTimeout(5);
Callable<Boolean> downloadTask = () -> {
try {
return ftpClient.retrieveFile(name, counterOutput);
} catch (IOException e) {
Logger.error(e.getMessage(), e);
return false;
}
};
Callable<Boolean> connectionCheckTask = () -> {
try {
while(true) {
Thread.sleep(5000);
ftpClient.getStatus();
}
} catch (SocketTimeoutException e) {
Logger.error("Connection is broken", e);
return false;
} catch (InterruptedException e) {
Logger.error(ex.getMessage, e);
return false;
}
};
ExecutorService execSvc = Executors.newCachedThreadPool();
Boolean result = execSvc.invokeAny(Arrays.asList(downloadTask, connectionCheckTask));
execSvc.shutdown();
我认为这不是完美的解决方案,但它对我有用。
于 2019-02-21T15:31:35.127 回答