2012-08-15 134 views
1

我看了很多例子,並試圖理解我做錯了什麼,但沒有成功,也許你可以幫助我。它總是停在第二個文件上,但第一個文件只是在c:\上大小爲0kb。 files_server.get(i)是ArrayList,其中包含我希望下載的所有文件。Java FTP下載進度

我的代碼:

public FTPConnection() { 

StartD std = new StartD(); 
std.start(); 
} 

class StartD extends Thread{ 

     @Override 
     public void run() 
     { 
     for (int i = 0; i < files_server.size(); i++) { 
      err = ftpDownload(files_server.get(i), "C:/"+ files_server.get(i)); 
      if (!err) 
       { 
       System.out.println("Error in download, breaking"); 
       break; 
       } 
      } 
     } 

     public boolean ftpDownload(String srcFilePath, String desFilePath) 
     { 
     try { 
      FileOutputStream desFileStream = new FileOutputStream(desFilePath); 
      InputStream input = mFTPClient.retrieveFileStream(srcFilePath); 
      byte[] data = new byte[1024]; 
      int count; 
      while ((count = input.read(data)) != -1) 
      { 
       desFileStream.write(data, 0, count); 
      } 
      desFileStream.close(); 

     } catch (Exception e) { 

      return false; 
     } 
    return true; 

    }} 

如果我使用finction:

public boolean ftpDownload(String srcFilePath, String desFilePath) { 
     boolean status = false; 
     try { 

      FileOutputStream desFileStream = new FileOutputStream(desFilePath); 
      status = mFTPClient.retrieveFile(srcFilePath, desFileStream); 
      desFileStream.close(); 
      return status; 
     } catch (Exception e) { 

     } 
     return status; 
    } 

代替,一切都運行得很好,但我不能老是監視文件下載進度。

+0

很多問題。例如,由於您沒有說出所有這些FTP的來源,代碼不能被複制。前1024個字節的數據永遠丟失。你應該附加一個可運行的測試用例 – Raffaele 2012-08-15 08:11:54

+0

你是什麼意思「代碼不能被複制」? 已修復「前1024個字節的數據永遠丟失」。還是行不通。 – DanM 2012-08-15 09:05:40

+0

[this](http://pastebin.com/ng5rw4sV)是可複製的,自包含代碼 – Raffaele 2012-08-15 10:28:16

回答

2

我只用它進行文件解壓縮,而不是FTP,但在這種情況下的InputStream緩衝區可以返回零,所以我會說這是值得嘗試改變你的while循環是這樣的:

while ((count = input.read(data)) >= 0) 

public int read(byte [] b)throws IOException

從輸入流中讀取一定數量的字節並將它們存儲到緩衝區數組b中。 實際讀取的字節數作爲整數返回。此方法會阻止,直到輸入數據可用,檢測到文件結尾, 或拋出異常。

如果b的長度爲零,則不讀取字節並返回0;

這也可能是你的兩倍分配數量,這可能去砍第一個字節關數據:

int count = input.read(data); 
while ((count = input.read(data)) != -1) 

所以不指定任何東西,當你把它聲明計數。

1

我們假設你的庫是來自commons-net包的FTP客戶端。要弄清楚代碼出了什麼問題並不容易,因爲我們無法運行它,並且因爲您的描述(第二個文件停止)是不夠的(它會拋出異常嗎?它會永久掛起嗎?沒有任何一方會完成影響?)。反正我有幾個建議的:

  1. 使用CountingOutputStream(Apache的公共-10)監測進展
  2. 使用ProtocolCommandListener登錄是怎麼回事

另外請注意,第一1024字節總是丟失。最終,我不知道將它放在C:\中的安全性與它在服務器上的名稱相同。在最好的情況下,它可能會導致許可問題,最糟糕的是它可能引發安全漏洞 - 無論如何,如果你對文件名有一定程度的控制,這並不適用,但是你可以考慮這個建議。

這是一個簡單的客戶端

public class FTP { 

    public static void main(String[] args) throws SocketException, IOException { 
     FTPClient client = new FTPClient(); 

     client.addProtocolCommandListener(new ProtocolCommandListener(){ 

      @Override 
      public void protocolCommandSent(ProtocolCommandEvent evt) { 
       logger.debug(evt.getMessage()); 

      } 

      @Override 
      public void protocolReplyReceived(ProtocolCommandEvent evt) { 
       logger.debug(evt.getMessage()); 
      } 

     }); 

     client.connect("ftp.mozilla.org"); 
     client.login("anonymous", ""); 
     client.enterLocalPassiveMode(); 

     OutputStream out = new CountingOutputStream(new NullOutputStream()) { 
      @Override 
      public void beforeWrite(int count) { 
       super.beforeWrite(count); 
       logger.info("Downloaded " + getCount() + " bytes"); 
      } 
     }; 

     for (String filename: new String[] {"MD5SUMS", "SHA1SUMS"}) 
      client.retrieveFile("pub/firefox/releases/15.0b4/" + filename, out); 

     out.close(); 
     client.disconnect(); 
    } 

    private static Logger logger; 

    static { 
     logger = Logger.getLogger(FTP.class.getCanonicalName()); 
    } 

} 

配置完成後,記錄器將輸出所有的原始套接字的對話,並且它可以幫助你更好地理解這個問題,只要它是在FTP側,而不是在應用程序IO