Я пытаюсь заставить работать следующий код:
string url = String.Format(@"SOMEURL");
string user = "SOMEUSER";
string password = "SOMEPASSWORD";
FtpWebRequest ftpclientRequest = (FtpWebRequest)WebRequest.Create(new Uri(url));
ftpclientRequest.Method = WebRequestMethods.Ftp.ListDirectory;
ftpclientRequest.UsePassive = true;
ftpclientRequest.Proxy = null;
ftpclientRequest.Credentials = new NetworkCredential(user, password);
FtpWebResponse response = ftpclientRequest.GetResponse() as FtpWebResponse;
Обычно это работает, но для 1 конкретного сервера выдается ошибка 500: синтаксис не распознается. Команда «Изменить каталог» отключена на проблемном сервере, и администратор сайта сказал мне, что .NET выдает команду «Изменить каталог» по умолчанию для всех FTP-подключений. Это правда? Есть ли способ отключить это?
EDIT: когда я вхожу в систему из командной строки, я нахожусь в правильном каталоге:
ftp> pwd
257 "/" - текущий каталог





Я думаю, что у нас была похожая проблема некоторое время назад, хотя я не помню точных деталей.
Чтобы запретить .net запускать команду cd, проверьте, установлен ли каталог по умолчанию для пользователя, в который вы входите, как каталог, в котором вы хотите работать. Вы можете просто использовать ftp-клиент командной строки, чтобы проверить это.
Я только что протестировал это на одном из наших серверов разработки, и действительно, .NET FtpWebRequest выпускает CWD:
new connection from 172.16.3.210 on 172.16.3.210:21 (Explicit SSL) hostname resolved : devpc sending welcome message. 220 Gene6 FTP Server v3.10.0 (Build 2) ready... USER testuser testuser, 331 Password required for testuser. testuser, PASS **** testuser, logged in as "testuser". testuser, 230 User testuser logged in. testuser, OPTS utf8 on testuser, 501 Please CLNT first. testuser, PWD testuser, 257 "/" is current directory. testuser, CWD / testuser, change directory '/' -> 'D:\testfolder' --> Access allowed. testuser, 250 CWD command successful. "/" is current directory. testuser, TYPE I testuser, 200 Type set to I. testuser, PORT 172,16,3,210,4,127 testuser, 200 Port command successful. testuser, NLST testuser, 150 Opening data connection for directory list. testuser, 226 Transfer ok. testuser, 421 Connection closed, timed out. testuser, disconnected. (00d00:05:01)
Это было без указания символа «/» в uri при создании объекта FtpWebRequest.
Если вы отлаживаете или просматриваете исходный код, в игру вступает класс под названием «FtpControlStream». См. Стек вызовов:
System.dll!System.Net.FtpControlStream.BuildCommandsList(System.Net.WebRequest req) Line 555 C#
System.dll!System.Net.CommandStream.SubmitRequest(System.Net.WebRequest request =
{System.Net.FtpWebRequest}, bool async = false, bool readInitalResponseOnConnect = true) Line 143 C#
System.dll!System.Net.FtpWebRequest.TimedSubmitRequestHelper(bool async) Line 1122 + 0x13 bytes C#
System.dll!System.Net.FtpWebRequest.SubmitRequest(bool async = false) Line 1042 + 0xc bytes C#
System.dll!System.Net.FtpWebRequest.GetResponse() Line 649 C#
Вызывается метод BuildCommandsList (). BuildCommandsList () создает список команд для отправки на FTP-сервер. Этот метод имеет следующий фрагмент кода:
if (m_PreviousServerPath != newServerPath) {
if (!m_IsRootPath
&& m_LoginState == FtpLoginState.LoggedIn
&& m_LoginDirectory != null)
{
newServerPath = m_LoginDirectory+newServerPath;
}
m_NewServerPath = newServerPath;
commandList.Add(new PipelineEntry(FormatFtpCommand("CWD", newServerPath), PipelineEntryFlags.UserCommand));
}
При первом подключении к серверу m_PreviousServerPath всегда имеет значение null, значение newServerPath равно «/» и вычисляется функцией с именем GetPathAndFileName () (вызывается за несколько строк до этого блока кода). GetPathAndFileName () вычисляет newServerPath как "/", если путь не указан или если "/" явно добавлен в конец uri 'ftp: // ....'.
Так что это, конечно, в конечном итоге приводит к добавлению команды CWD в командный конвейер, потому что null! = "/".
Вкратце, к сожалению, вы не можете изменить это поведение, потому что оно записано в исходном коде.
Вот решение: используйте эту бесплатную клиентскую библиотеку FTP с открытым исходным кодом для C#, созданную Дэном на C-SharpCorner.com: http://www.c-sharpcorner.com/uploadfile/danglass/ftpclient12062005053849am/ftpclient.aspx
Вот пример кода для загрузки файла:
FtpClient ftp = new FtpClient(FtpServer,FtpUserName,FtpPassword);
ftp.Login();
ftp.Upload(@"C:\image.jpg");
ftp.Close();
Эта библиотека отлично работает "из коробки", но ее также можно легко расширить и изменить.
Хотя пост вроде как давным-давно ... неважно, я дам ответ здесь.
Вместо использования ftp://server/path в качестве URI попробуйте ftp://server/%2fpath/.
Добавленный %2f "- это просто экранированный /, добавление которого заставит C# рассматривать весь путь как абсолютный.
В противном случае C# войдет в ftp://server/ с именем пользователя, перейдет в домашнюю папку пользователя, затем cd по указанному пути, так что ваш путь станет user_home_path/path, что может быть нежелательно.
Более подробную информацию можно найти на msdn http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx
Надеюсь это поможет.
Используя информацию выше, у меня это сработало.
Отправляет CWD - ftpState.ftpRequest = GetRequest ("ftp://192.168.0.2/tmp/file2download")
Не отправляет CWD - ftpState.ftpRequest = GetRequest ("ftp://192.168.0.2//tmp/file2download") обратите внимание на // после IP-адреса сервера (или имени)
DotNET версии 2.0
Private Function GetRequest(ByVal URI As String) As FtpWebRequest
'create request
Dim result As FtpWebRequest = CType(FtpWebRequest.Create(URI), FtpWebRequest)
Return result
End Function