2010-02-20 63 views
4

我想要獲取每個文件在FTP服務器上的文件名,文件大小和上次修改時間,然後用它填充listView。C#使用ftpRequest獲取完整文件列表的速度很慢

它工作得很好,直到我切換FTP主機,現在它真的很慢,儘管新的主機在真正的FTP客戶端速度一樣快。

明顯的原因是爲什麼?

另外,每次發送登錄憑證真的需要嗎?

我使用第一種方法來獲得一個字符串數組,然後遍歷它並使用在各個項目上第二個獲得文件大小:

public static string[] GetFileList() 
    { 
     string[] downloadFiles; 
     StringBuilder result = new StringBuilder(); 
     FtpWebRequest request; 
     try 
     { 
      request = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://mysite.se/")); 
      request.UseBinary = true; 
      request.Credentials = new NetworkCredential(settings.Username, settings.Password); 
      request.Method = WebRequestMethods.Ftp.ListDirectory; 
      request.UseBinary = true; 

      WebResponse response = request.GetResponse(); 
      StreamReader reader = new StreamReader(response.GetResponseStream()); 

      string line = reader.ReadLine(); 
      while (line != null) 
      { 
       result.Append(line); 
       result.Append("\n"); 
       line = reader.ReadLine(); 
      } 
      // to remove the trailing '\n' 
      result.Remove(result.ToString().LastIndexOf('\n'), 1); 
      reader.Close(); 
      response.Close(); 
      return result.ToString().Split('\n'); 
     } 
     catch (Exception ex) 
     { 
      System.Windows.Forms.MessageBox.Show(ex.Message); 
      downloadFiles = null; 
      return downloadFiles; 
     } 
    } 

    public static int GetFileSize(string file) 
    { 
     //MessageBox.Show("getting filesize..."); 

     StringBuilder result = new StringBuilder(); 
     FtpWebRequest request; 
     try 
     { 
      request = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://mysite.se/" + file)); 
      request.UseBinary = true; 
      request.Credentials = new NetworkCredential(settings.Username, settings.Password); 
      request.Method = WebRequestMethods.Ftp.GetFileSize; 

      int dataLength = (int)request.GetResponse().ContentLength; 

      return dataLength; 
     } 
     catch (Exception ex) 
     { 
      //System.Windows.Forms.MessageBox.Show(ex.Message); 
      return 1337; 
     } 
    } 

回答

7

的問題是,每個GetFileSize調用有重新連接到服務器併發出文件大小的請求。如果您可以設置使用單個持久連接,那麼您將節省連接時間,但仍會花費大量時間爲每個文件發送請求並等待響應。

(編輯:這可能已經是這樣的MSDN說:Multiple FtpWebRequests reuse existing connections, if possible.

如果使用ListDirectoryDe​​tails而非ListDirectory,那麼服務器可能會發下來的更多信息(文件大小,權限等)以及每個文件名。這不會再需要比ListDirectory更長的時間了,您可以從每行中取出名稱和大小,然後存儲大小以備後用。

但是,不同的服務器可能會發送不同格式的信息,有些可能根本不會發送大小信息,所以如果您需要您的程序可靠地使用任何FTP服務器,這可能沒有幫助。

4

不正確的,甚至好回答:

下面是說明其工作原理PowerShell的測試例如:

$request=[System.Net.FtpWebRequest]::Create('ftp://ftp.hp.com/control/SavvisLoad.whp-ftp.xml') 
$request.UseBinary=$false 
$request.Method=[System.Net.WebRequestMethods+Ftp]::GetDateTimestamp 
$request.GetResponse() 

它使用一個公共的HP服務器和演示如何獲取文件的大小。

ListDirectoryDe​​tails獲取文件夾信息。

上面最大的錯誤是模式設置爲二進制。所有目錄列表和文件信息必須使用文本模式。

1

這是一個經過驗證的快速獲取目錄列表的方法。它可以像使用PowerShell一樣進行測試。

[System.Net.FtpWebRequest]$request = [System.Net.WebRequest]::Create("ftp://ftp.hp.com/control") 
#$request.Credentials=New-Object System.Net.NetworkCredential('Anonymous','[email protected]') 
$request.Method = [System.Net.WebRequestMethods+FTP]::ListDirectoryDetails 
$request.UseBinary=$false 
$response=$request.GetResponse() 
$stream=$response.GetResponseStream() 
$b=new-object byte[] 1024 
$stream.Read($b,0,$b.Count) 
$b|%{$s+=[char]$_} 
$s