Как получить размер файла каталогов по протоколу FTP в приложении .NET - PullRequest
3 голосов
/ 25 октября 2011

В настоящее время я создаю небольшое консольное приложение .NET для автоматического резервного копирования некоторых моих файлов на мой сервер. Проблема, с которой я сталкиваюсь, заключается в том, что на моем конце была плохая погода, что привело к некоторым сбоям питания и сети. За это время я заметил, что значительная часть моих файлов не прошла или была повреждена. Мне было интересно, есть ли способ получить размер папки на другом конце и посмотреть, совпадают ли имена файлов, количество файлов и общий размер каталога. Я пробовал WinSCP и NcFTP как способы передачи файлов, но я не видел ничего относительно получения правильного размера файла.

Это в значительной степени передача из окон в окна, поэтому, если есть аргумент командной строки, который возвращает мне размер через FTP-клиент, это было бы здорово.

Ответы [ 3 ]

1 голос
/ 04 сентября 2017

Нет стандартной команды 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 # для разбора ответа WebRequestMethods.Ftp.ListDirectoryDetails FTP


В качестве альтернативы вы можете использовать стороннюю реализацию FTP-клиента, которая поддерживает современную команду MLSD.

Например, Сборка WinSCP .NET поддерживает это.

И даже есть удобный метод 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)

1 голос
/ 25 октября 2011

Нет стандартного способа запросить «общий размер файлов в этом каталоге». Вы можете запросить каждый размер файла индивидуально через SIZE file.txt, или вы можете запросить ls -l всего каталога и проанализировать размеры файла.

0 голосов
/ 26 октября 2011

Я думаю, что вам лучше всего получить полный список файлов, а затем отправлять их по одному за раз. Если во время передачи не удается установить соединение, загрузка файла не будет выполнена. Если загрузка файла прошла успешно, вы можете удалить это имя файла из списка.

, поскольку вы упомянули NET в своих тегах, возможно, вам следует поискать здесь для примера того, как это сделать в C #. VB.Net будет похожим, но он даст вам представление.

Вы можете получить список каталогов, как показано здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...