Почему 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, вы можете просто проверить, возвращает ли он что-то другое для существующей, но пустой папки. Если это так, вы можете легко различить этот и этот пустой ответ и рассматривать пустой ответ как ошибку "не найден" в вашей программе.