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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7891677/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 18:21:21  来源:igfitidea点击:

How to get a directories file size from an FTP protocol in a .NET application

.netwindowsftpwinscp

提问by Seb

I am currently making a small .NET console application to do an automateed backup of some of my files onto my server. The issue that I am running into is that I've had some bad weather on my end which led to some power and network outages. During this time I noticed that a good portion of my files didn't go through or got corrupt. I was wondering if there was a way to get a size of the folder on the other end and see if the file names, number of files, and total directory size match up. I've tried WinSCP and NcFTP as ways to transfer files over, but I haven't seen anything regarding getting a proper filesize.

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

This is pretty much a windows to windows transfer so if there is a command line argument that gives me back a size through the FTP client that would be great.

这几乎是一个 windows 到 windows 的传输,所以如果有一个命令行参数可以通过 FTP 客户端给我一个大小,那就太好了。

采纳答案by Raymond Chen

There is no standard way to request "total size of files in this directory". You can ask for each file size individually via SIZE file.txt, or you can ask for ls -lof an entire directory and parse the file sizes out.

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

回答by Martin Prikryl

There's no standard FTP command to retrieve a directory size.

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

You have to recursively iterate all subdirectories and files and sum the sizes.

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

This is not easy with .NET framework/FtpWebRequest, as it does not support the MLSDcommand, which is the only portable way to retrieve directory listing with file attributes in FTP protocol.

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

All you can do is to use LISTcommand (ListDirectoryDetails) and try to parse a server-specific listing. Many FTP servers use *nix-style listing. But many servers use a different format. The following example uses *nix format:

您所能做的就是使用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;
}

Use it like:

像这样使用它:

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


If your server uses DOS/Windows listing format, see C# class to parse WebRequestMethods.Ftp.ListDirectoryDetails FTP response

如果您的服务器使用 DOS/Windows 列表格式,请参阅 C# 类解析 WebRequestMethods.Ftp.ListDirectoryDe​​tails FTP 响应



Alternatively you can use a 3rd party FTP client implementation that supports the modern MLSDcommand.

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

For example WinSCP .NET assemblysupports that.

例如WinSCP .NET 程序集支持这一点。

And it even has handy Session.EnumerateRemoteFilesmethod, which makes calculating directory size easy task:

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

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

A complete code would be like:

完整的代码如下:

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();
}

(I'm the author of WinSCP)

(我是 WinSCP 的作者)

回答by ChrisBD

I think that your best bet is to obtain a full list of files and then send them one at a time. If the connection fails during transfer then that file upload will fail. If a file upload is successful then you can remove that file name from the list.

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

as you've mentioned NET in your tags perhaps you should look herefor an example of how to perform it in C#. VB.Net will be similar, but it will give you an idea.

正如您在标签中提到的 NET,也许您应该在此处查看如何在 C# 中执行它的示例。VB.Net 会类似,但它会给你一个想法。

You can get a directory list as shown here.

你可以得到如图所示目录列表在这里