Почему FtpWebRequest возвращает пустой поток для этого существующего каталога?

Я не уверен, почему я получаю этот результат. Я запускаю это на сервере Linux. (Это общая учетная запись хостинга моего небольшого веб-сайта.)

Файлы сгруппированы следующим образом:

и Another Dir имеет один файл внутри:

Поэтому я пытаюсь получить содержимое badname каталог внутри 1somelongdir1234567 каталог, который не существует на сервере, используя этот код:

try
{
    FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(
        "ftp://server12.some-domain.com/public_html/1somelongdir1234567/badname");
    ftpRequest.EnableSsl = true;
    ftpRequest.Credentials = new NetworkCredential("user", "password");
    ftpRequest.KeepAlive = true;
    ftpRequest.Timeout = -1;

    ftpRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

    using (FtpWebResponse response1 = (FtpWebResponse)ftpRequest.GetResponse())
    {
        //*****BEGIN OF EDIT*****
        Console.WriteLine(response1.StatusDescription);
        Console.WriteLine(response1.StatusCode);
        //*****END OF EDIT*****

        using (StreamReader streamReader = new StreamReader(response1.GetResponseStream()))
        {
            List<string> arrList = new List<string>();

            for (; ; )
            {
                string line = streamReader.ReadLine();

                //I get to here, where `line` is null????

                if (string.IsNullOrEmpty(line))
                    break;

                arrList.Add(line);

                //*****BEGIN OF EDIT*****
                Console.WriteLine(line);
                //*****END OF EDIT*****
            }
        }
    }
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

Итак, как вы видите, такой папки нет badname но вместо того, чтобы бросить исключение, мой ftpRequest.GetResponse() успешно, а затем streamReader.ReadLine() возвращается null как я показал в коде выше.

Более странно, если я предоставлю фактический каталог как таковой:

    FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(
        "ftp://server12.some-domain.com/public_html/1somelongdir1234567/Another%20Dir");

streamReader.ReadLine() все еще возвращается null,

Может кто-нибудь объяснить почему?

РЕДАКТИРОВАТЬ: ОК, ребята, я обновил код выше, чтобы получить код состояния. Я все еще озадачен, хотя.

Во-первых, вот три значения URI подключения и ответ / вывод, который я получаю:

Пример 1:

//Existing folder
"ftp://server12.some-domain.com/public_html/1somelongdir1234567"

Выход:

150 Accepted data connection

OpeningData
drwxr-xr-x    3 username   username         4096 Sep  5 05:51 .
drwxr-x---  118 username   99               4096 Sep  5 05:54 ..
drwxr-xr-x    2 username   username         4096 Sep  5 05:52 Another Dir
-rw-r--r--    1 username   username           11 Sep  5 05:51 test123.txt

Пример 2:

//Another existing folder
"ftp://server12.some-domain.com/public_html/1somelongdir1234567/Another%20Dir"

Выход:

150 Accepted data connection

OpeningData

Пример 3:

//Nonexistent folder
"ftp://server12.some-domain.com/public_html/1somelongdir1234567/SomeBogusName"

Выход:

150 Accepted data connection

OpeningData

Так почему же он дает мне тот же результат для примера 2, что и для 3?

Что касается того, что это FTP-сервер, я не смог увидеть его ни в журналах сети, ни в FtpWebRequest сам. Вот что я смог получить от Microsoft Network Monitor:

Добро пожаловать в Pure-FTPd [privsep] [TLS] ----------..
220-Вы являетесь пользователем 4 из 50 разрешенных... 220-Местное время сейчас 13:14. Порт сервера: 21...
220-Это частная система - без анонимного входа..
Подключения 220-IPv6 также приветствуются на этом сервере...
220 Вы будете отключены после 15 минут бездействия...

2 ответа

Решение

URL для ListDirectory/ListDirectoryDetails метод должен заканчиваться косой чертой, в общем.

Без косой черты, результаты имеют тенденцию быть неопределенными.

WebRequest.Create("ftp://example.com/public_html/1somelongdir1234567/Another%20Dir/");

Как отметил stuartd, в ответ вы получите код состояния FTP. Насколько я знаю, из-за того, как работают команды FTP, вы никогда не получите исключение, когда сервер не сможет выполнить запрошенную вами команду. Вместо этого сервер просто скажет вам, что произошел сбой, через код ответа FTP.

Вы должны понять, что у FTP нет стандартов для текста, который он отправляет обратно, потому что он никогда не был предназначен для машинной интерпретации его ответов. Если у вас есть время, посмотрите код FileZilla и проверьте его класс на предмет интерпретации списков файлов (directorylistingparser.cpp). Есть десятки способов интерпретировать это, и приложение будет просто пробовать их все, пока один не сработает. Потому что, если вы не знаете, к какому типу FTP вы подключаетесь, это единственный способ сделать это.

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

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

Другие вопросы по тегам