2010-02-20 65 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