C # Получение полного списка файлов с использованием ftpRequest идет медленно - PullRequest
4 голосов
/ 20 февраля 2010

Я хочу получить имя файла, размер файла и время последнего изменения каждого файла на FTP-сервере, а затем заполнить его списком.

Он работал очень хорошо, пока я не переключил 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;
        }
    }

Ответы [ 3 ]

7 голосов
/ 20 февраля 2010

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

(Редактировать: это может уже иметь место. MSDN говорит: Несколько запросов FtpWeb, если возможно, повторно используют существующие соединения. )

Если вы используете ListDirectoryDetails, а не ListDirectory, то сервер, вероятно, будет отправлять больше информации (размер файла, разрешения и т. Д.) Вместе с каждым именем файла. Это не займет больше времени, чем просто выполнение ListDirectory, и вы можете извлечь имя и размер из каждой строки и сохранить размеры для дальнейшего использования.

Однако разные серверы могут отправлять информацию в разных форматах, а некоторые могут вообще не отправлять информацию о размере, поэтому это может не помочь, если вам нужна программа для надежного использования любого FTP-сервера.

4 голосов
/ 01 декабря 2012

Не правильный или даже хороший ответ:

Вот пример теста 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 и показано, как получить размер файла.

ListDirectoryDetails получает информацию о папке.

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

1 голос
/ 01 декабря 2012

Вот проверенный и быстрый способ получить список каталогов. Он может быть протестирован как есть с 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
...