Ошибки загрузки C # FTP с Аутентификацией & System.NotImplementedException - PullRequest
0 голосов
/ 19 ноября 2018

При попытке загрузить файл с удаленного FTP-сервера выдается следующее исключение:

The underlying connection was closed: The server committed a protocol violation.

Файл ранее был загружен через класс WebClient, но я пытаюсь реализовать новое решение с FtpWebRequest для этого MSFT-примера .

Эта ошибка выдает при вызове request.GetResponse() ниже:

string remoteFilePath = 
    ConfigWrapper.GetEncryptedString(
        "FtpFeedPath", 
         @"ftp://subdomain.domain.com/folder/subfolder/file.xml.gz");
string tempFilePath = Path.GetTempPath() + @"\ftpFile.gz";
string fileExtractName = Path.GetTempPath() + @"\ftpFile\ftpFile.xml";

if (!Directory.Exists(Path.GetDirectoryName(fileExtractName)))
{
    Directory.CreateDirectory(Path.GetDirectoryName(fileExtractName));
}

FtpWebRequest request = 
    (FtpWebRequest)WebRequest.Create(remoteFilePath);
request.Method = WebRequestMethods.Ftp.DownloadFile;

request.Timeout = -1;
request.UseBinary = true;
request.KeepAlive = true;
request.UsePassive = false;


request.Credentials = new NetworkCredential(
    ConfigWrapper.GetEncryptedString(
        "FtpUserName", 
        "123456"),
    ConfigWrapper.GetEncryptedString(
        "FtpPassword", 
        "password"),
    remoteFilePath); 

FtpWebResponse response = (FtpWebResponse)request.GetResponse();

Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
Console.WriteLine(reader.ReadToEnd());
Console.WriteLine($"Download Complete, status{response.StatusDescription}");

reader.Close();
response.Close();

Копание в исключении показывает это сообщение: ContentType = '((System.Net.WebException)ex).Response.ContentType' threw an exception of type 'System.NotImplementedException'

Большинство других ответов StackOverflow, относящихся к этой проблеме, похоже, разрешаются после изменения свойства KeepAlive. Это не тот случай, здесь. Другая распространенная рекомендация - получить сетевую трассировку, но большинство сообщений не обсуждали проблему и не извлекали трассировку. След ниже.

Одна вещь, которая выделяется из трассировки, заключается в том, что команда USER FTP включает полный путь к файлу, а не только имя пользователя сервера. Есть ли способ сначала установить аутентификацию на сервере, прежде чем запрашивать загрузку с полным путем? Пример MSFT, похоже, сразу указывает весь путь.

System.Net Information: 0 : [25984] RAS supported: True
System.Net Information: 0 : [25984] FtpControlStream#43231651 - Created         
   connection from XX.XX.XX.XX:65106 to XX.XX.XX.XX:21.
System.Net Information: 0 : [25984] Associating FtpWebRequest#58529038 with     FtpControlStream#43231651
System.Net Information: 0 : [25984] FtpControlStream#43231651 - Received response [220 Remote FTP Server.  All transfers are logged.]
System.Net Information: 0 : [25984] FtpControlStream#43231651 - Sending command [USER ftp://subdomain.domain.com/folder/subfolder/file.xml.gz\1850771]
System.Net Information: 0 : [25984] FtpWebRequest#58529038::(Releasing FTP connection#43231651.)
System.Net Error: 0 : [25984] Exception in FtpWebRequest#58529038::GetResponse - The underlying connection was closed: The server committed a protocol violation..
   at System.Net.FtpWebRequest.SyncRequestCallback(Object obj)
   at System.Net.FtpWebRequest.RequestCallback(Object obj)
   at System.Net.CommandStream.Dispose(Boolean disposing)
   at System.IO.Stream.Close()
   at System.IO.Stream.Dispose()
   at System.Net.ConnectionPool.Destroy(PooledStream pooledStream)
   at System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse)
   at System.Net.FtpWebRequest.FinishRequestStage(RequestStage stage)
   at System.Net.FtpWebRequest.GetResponse()

1 Ответ

0 голосов
/ 19 ноября 2018

Одна вещь, которая выделяется из трассировки, заключается в том, что команда USER FTP включает полный путь к файлу, а не только имя пользователя сервера.

Я полагаю, что вы сами делаете это, передавая URL (remoteFilePath) в domain параметр NetworkCredential:

request.Credentials = new NetworkCredential(
    ConfigWrapper.GetEncryptedString(
        "FtpUserName", 
        "123456"),
    ConfigWrapper.GetEncryptedString(
        "FtpPassword", 
        "password"),
    remoteFilePath); 

Это не имеет смысла.Если вам нужен домен, передайте домен, а не URL.Хотя в большинстве случаев домен используется только с IIS, это не похоже на ваш случай.Поэтому обычно вы используете перегрузку конструктора NetworkCredential только с двумя аргументами (имя пользователя и пароль).

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