[英]File Download from a FTP Server using apache FTPClient
我正在使用apache的FTPClient从FTP服务器下载文件。 我的情况是-FTP服务器可能会失去网络连接,并且可能最多保持1天处于断开连接状态。 重新连接后,应从剩余位置开始下载文件。 我正在使用以下代码连接到服务器,然后从服务器下载文件
public void retrieve(String server, int port, String username,
String password, String remote, String local, int fileType,
ProgressHandler progressHandler) throws Exception {
final FTPClient ftp = new FTPClient();
Date date = new Date();
long startTime_ms = date.getTime();
if (progressHandler != null) {
ftp.setCopyStreamListener(new FtpCopyStreamListener(progressHandler));
}
ftpConnect(server,ftp, port,startTime_ms);
if(ftp.getReplyCode()==0 || !String.valueOf(ftp.getReplyCode()).startsWith("2")){
cleanup(ftp, "Could not log into server: " + server, null);
return;
}
boolean loggedIn = false;
try {
if (username == null || username.isEmpty()) {
username = "anonymous";
password = System.getProperty("user.name") + "@"
+ InetAddress.getLocalHost().getHostName();
}
if (!ftp.login(username, password)) {
ftp.logout();
cleanup(ftp, "Could not log into server: " + server, null);
}
loggedIn = true;
ftp.setFileType(fileType);
ftp.enterLocalPassiveMode();
OutputStream output = null;
try {
output = new FileOutputStream(local);
LOGGER.info("About to download " + remote + " from " + server
+ " on " + (port > 0 ? port : ftp.getDefaultPort())
+ " to " + local);
ftp.setControlKeepAliveTimeout(300);
boolean isFileDownloaded = false;
try{
isFileDownloaded = ftp.retrieveFile(remote, output);
}
catch(IOException ex){
if(ftp.isConnected()){
try{
int retryCode = 0;
while (!String.valueOf(retryCode).startsWith("2") && (new Date().getTime() < (startTime_ms + TOTAL_DURATION_MSECS))){
try{
retryCode = ftp.retr(local);
}catch(Exception e1){
Thread.sleep(1000);
System.out.println("File not downloaded !! " + e1.toString());
ftpConnect(server, ftp, port, startTime_ms);
}
}
}catch(Exception e){
//ftp.getReplyCode()
//throw e;
//disconnect(ftp);
//ftpConnect(server, ftp, port, startTime_ms);
System.out.println("File not downloaded !! " + e.toString());
}
}
}
if(isFileDownloaded){
LOGGER.info("Finished downloading " + remote + " from "
+ server + " on "
+ (port > 0 ? port : ftp.getDefaultPort()) + " to "
+ local);
}
else{
System.out.println("File not downloaded !! ");
}
}catch(IOException io){
io.printStackTrace();
throw io;
}
finally {
if (output != null) {
try {
output.close();
} catch (IOException f) {
LOGGER.severe("output.close() error: "
+ ServiceUtils.stackToString(f));
}
}
}
}
catch (FTPConnectionClosedException e) {
LOGGER.severe("Server closed connection: " + server + " "
+ ServiceUtils.stackToString(e));
throw e;
} catch (IOException e) {
LOGGER.severe("IOException, server: " + server + " "
+ ServiceUtils.stackToString(e));
throw e;
} finally {
if (loggedIn) {
try {
ftp.logout();
} catch (IOException f) {
LOGGER.severe("ftp.logout() error: "
+ ServiceUtils.stackToString(f));
}
}
disconnect(ftp);
}
}
我的问题基本上是,retrieveFile()方法是否失败,无论如何我都可以重新连接并从断开连接的地方开始下载。
现在,我使用Microsoft IIS服务器作为FTP服务器,但是在生产环境中,它将是FileZilla FTP服务器。
任何帮助表示赞赏。 谢谢
抱歉,回复太晚了。 这是我为解决问题所做的工作:
保持写入的字节数,并使用相同的输出流进行写入。
BufferedInputStream inputStream = null; BufferedOutputStream outputStream = null; InputStream in = null; int osCount = 0; in = ftp.retrieveFileStream(remote); inputStream = new BufferedInputStream(in); File localFile = new File(local, fileName); outputStream = new BufferedOutputStream(new FileOutputStream(localFile)); for (int read = inputStream.read(); read != -1; read = inputStream.read()) { outputStream.write(read); osCount++; } outputStream.flush(); if (osCount < fileSize) { System.out.println(fileName + ": Errored out !!!"); BufferedInputStream inputStream1 = null; InputStream in1 = null; if (ftp.isConnected()) { try { while (osCount < fileSize && new Date().getTime() < (startTime_ms + TOTAL_DURATION_MSECS)) { try { disconnect(ftp); ftpConnect(server, ftp, port, startTime_ms); ftp.login(username, password); ftp.setRestartOffset(osCount); System.out.println(fileName + ": Re reading from position " + osCount); in1 = ftp.retrieveFileStream(remote); inputStream1 = new BufferedInputStream(in1); for (int read = inputStream1.read(); read != -1; read = inputStream1.read()) { outputStream.write(read); osCount++; } outputStream.flush(); if(FTPReply.isPositiveCompletion(ftp.getReplyCode())){ isErrored = true; break; } } catch (Exception e1) { Thread.sleep(1000); LOGGER.severe(fileName + ": File not downloaded " + server + " " + ServiceUtils.stackToString(e1)); } } } catch (Exception e) { LOGGER.severe(fileName + ": File not downloaded " + server + " " + ServiceUtils.stackToString(e)); } } }
FTPCLient.restart(...)
protected
。 我认为setRestartOffset(...)
和retrieveFile(...)
是setRestartOffset(...)
的方法: “注意:如果您使用过setRestartOffset(long),则文件数据将从选定的偏移量开始。” 。
我还会捕获CopyStreamException
而不是仅捕获IOException
: “ CopyStreamException允许您确定传输的字节数 ”。
在进入重试块之前,请检查ftp.isConnected()
,但是您写了“ FTP服务器网络连接松动,并且可能保持断开连接” 。 我猜想,如果您输入此catch块,则连接性已经丢失,这就是根本无法进入此块的原因之一。
ftp.retr(...)
在做什么? 重试,是的,但是它能按预期工作吗?
如果通过以下方式调试代码,会得到什么?
ftp.isConnected()
处设置断点 ftp.isConnected()
的值 true
(不太可能,但是谁知道) ftp.retr(...)
返回什么?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.