如何从.NET应用程序中的FTP协议获取目录文件大小

时间:2011-10-25 15:26:46

标签: .net windows ftp winscp

我目前正在制作一个小型.NET控制台应用程序,以便将我的部分文件自动备份到我的服务器上。我遇到的问题是我的天气有些恶劣导致一些电力和网络中断。在这段时间里,我注意到我的文件的很大一部分没有通过或损坏。我想知道是否有办法在另一端获得文件夹的大小,看看文件名,文件数和总目录大小是否匹配。我已经尝试过将WinSCP和NcFTP作为传输文件的方法,但我还没有看到任何关于获取正确文件大小的内容。

这几乎是Windows转移的窗口,所以如果有一个命令行参数,通过FTP客户端返回一个大小很好。

3 个答案:

答案 0 :(得分:1)

没有标准方法可以请求“此目录中文件的总大小”。您可以通过SIZE file.txt单独询问每个文件大小,也可以询问整个目录的ls -l并解析文件大小。

答案 1 :(得分:1)

没有标准的FTP命令来检索目录大小。

您必须递归迭代所有子目录和文件并对大小求和。

使用.NET framework / FtpWebRequest并不容易,因为它不支持MLSD命令,这是在FTP协议中使用文件属性检索目录列表的唯一可移植方式。

您所能做的就是使用LIST命令(ListDirectoryDetails)并尝试解析特定于服务器的列表。许多FTP服务器使用* nix风格的列表。但是许多服务器使用不同的格式。以下示例使用* nix格式:

static long CalculateFtpDirectorySize(string url, NetworkCredential credentials)
{
    FtpWebRequest listRequest = (FtpWebRequest)WebRequest.Create(url);
    listRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
    listRequest.Credentials = credentials;

    List<string> lines = new List<string>();

    using (FtpWebResponse listResponse = (FtpWebResponse)listRequest.GetResponse())
    using (Stream listStream = listResponse.GetResponseStream())
    using (StreamReader listReader = new StreamReader(listStream))
    {
        while (!listReader.EndOfStream)
        {
            lines.Add(listReader.ReadLine());
        }
    }

    long result = 0;
    foreach (string line in lines)
    {
        string[] tokens =
            line.Split(new[] { ' ' }, 9, StringSplitOptions.RemoveEmptyEntries);
        string name = tokens[8];
        string permissions = tokens[0];

        string fileUrl = url + name;

        if (permissions[0] == 'd')
        {
            result += CalculateFtpDirectorySize(fileUrl + "/", credentials);
        }
        else
        {
            result += long.Parse(tokens[4]);
        }
    }

    return result;
}

使用它像:

var credentials = new NetworkCredential("username", "password");
long size = CalculateFtpDirectorySize("ftp://ftp.example.com/", credentials);

如果您的服务器使用DOS / Windows列表格式,请参阅C# class to parse WebRequestMethods.Ftp.ListDirectoryDetails FTP response

或者,您可以使用支持现代MLSD命令的第三方FTP客户端实现。

例如WinSCP .NET assembly支持。

它甚至还有方便的Session.EnumerateRemoteFiles方法,这使得计算目录大小变得容易:

var files = session.EnumerateRemoteFiles("/", null, EnumerationOptions.AllDirectories);
long size = files.Select(fileInfo => fileInfo.Length).Sum();

完整的代码如下:

SessionOptions sessionOptions = new SessionOptions
{
    Protocol = Protocol.Ftp,
    HostName = "ftp.example.com",
    UserName = "username",
    Password = "password",
};

using (Session session = new Session())
{
    // Connect
    session.Open(sessionOptions);

    var files = session.EnumerateRemoteFiles("/", null, EnumerationOptions.AllDirectories);
    long size = files.Select(fileInfo => fileInfo.Length).Sum();
}

(我是WinSCP的作者)

答案 2 :(得分:0)

我认为您最好的选择是获取完整的文件列表,然后一次发送一个。如果在传输过程中连接失败,则该文件上载将失败。如果文件上传成功,则可以从列表中删除该文件名。

正如您在标记中提到的.NET,或许您应该查看here以获取如何在C#中执行它的示例。 VB.Net将是类似的,但它会给你一个想法。

您可以获得如here所示的目录列表。