[英]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.