C# 使用 ftpRequest 获取完整的文件列表很慢

Posted

技术标签:

【中文标题】C# 使用 ftpRequest 获取完整的文件列表很慢【英文标题】:C# Getting a complete file list using ftpRequest is slow 【发布时间】:2010-02-20 16:25:25 【问题描述】:

我想获取 FTP 服务器上每个文件的文件名、文件大小和最后修改时间,然后用它填充一个 listView。

在我切换 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;
        
    

【问题讨论】:

【参考方案1】:

问题是每个 GetFileSize 调用都必须重新连接到服务器并发出文件大小请求。如果您可以设置使用单个持久连接,那么您将节省连接时间,但仍会花费大量时间为每个文件发送请求并等待响应。

(编辑:可能已经是这种情况了。MSDN 说:Multiple FtpWebRequests reuse existing connections, if possible.)

如果您使用 ListDirectoryDe​​tails 而不是 ListDirectory,那么服务器可能会连同每个文件名一起发送更多信息(文件大小、权限等)。这不会比只做 ListDirectory 花费任何时间,而且您可以从每一行中提取名称和大小并存储大小以供以后使用。

但是,不同的服务器可能会以不同的格式发送信息,有些可能根本不发送大小信息,因此如果您需要您的程序可靠地使用任何 FTP 服务器,这可能无济于事。

【讨论】:

【参考方案2】:

不是一个正确甚至是好的答案:

这是一个展示其工作原理的 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 获取文件夹信息。

上面最大的错误是模式设置为二进制。所有目录列表和文件信息都必须使用文本模式。

【讨论】:

【参考方案3】:

这是获得目录列表的一种行之有效且快速的方法。可以使用 PowerShell 按原样进行测试。

[System.Net.FtpWebRequest]$request = [System.Net.WebRequest]::Create("ftp://ftp.hp.com/control")
#$request.Credentials=New-Object System.Net.NetworkCredential('Anonymous','johnjones3@msn.com')
$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

【讨论】:

以上是关于C# 使用 ftpRequest 获取完整的文件列表很慢的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中使用正则表达式从完整路径解析文件名

获取文件C#的相对路径

C#当前程序路径获取

C# WinForm获取当前路径汇总

C#获取当前程序运行路径的方法集合

C#获取当前程序运行路径的方法集合