2012-04-18 5 views
2

Я пытаюсь подключиться к FTP-серверу и загружать файл, но у меня проблемы.Почему FtpWebRequest выбрасывает WebException точно в конце длинной передачи?

Первоначально я использовал WebClient.DownloadFileAsync и он работал отлично для небольшого файла, но большой файл не достигнет конца загрузки, но не называют DownloadFileCompleted ...

Я попытался переключиться на FtpWebRequest и использование FileStream для записать файл, используя стандартный метод:

var FtpRequest = WebRequest.Create(uri) as FtpWebRequest 
FtpRequest.Credentials = _Credentials; 
FtpRequest.Method = WebRequestMethods.Ftp.DownloadFile; 

using(var InputResponse = (FtpWebResponse)FtpRequest.GetResponse()) 
using (var InputStream = InputResponse.GetResponseStream()) 
using (var OutputStream = new FileStream(_DownloadDirectory + "\\" + fileName, FileMode.Create)) 
{ 
    var Buffer = new byte[1024]; 
    int TotalReadBytesCount = 0; 
    int ReadBytesCount; 
    while ((ReadBytesCount = InputStream.Read(Buffer, 0, Buffer.Length)) > 0) 
    { 
     OutputStream.Write(Buffer, 0, ReadBytesCount); 
     TotalReadBytesCount += ReadBytesCount; 
     var Progress = (int)(((double)TotalReadBytesCount/(double)FileSize) * 100); 
     UpdateProgressBar(progressBar, Progress); 
    } 
} 

Это один также отлично работает с небольшими файлами, но с большим файлом будет загружать весь файл, а затем я буду получать System.Net.WebException в InputStream.Read.

EDIT: исключение перемещается в зависимости от того, как структурирован код ... удаление «использования» статусов и закрытие каждого потока, а результат ответа - исключение, создаваемое последним x.close(). Также я отмечаю, что TotalBytesReceived is == to fileSize, поэтому загрузка технически завершена. END EDIT

Внутреннее исключение: базовое соединение было закрыто: произошла непредвиденная ошибка при приеме.

После включения system.Net.Tracing я получил следующее: логфайл

System.Net Verbose: 0 : [2440] WebRequest::Create(ftp://ftp.******.com/) 
System.Net Information: 0 : [2440] FtpWebRequest#63621045::.ctor(ftp://ftp.******.com/) 
System.Net Verbose: 0 : [2440] Exiting WebRequest::Create()  -> FtpWebRequest#63621045 
System.Net Verbose: 0 : [2440] FtpWebRequest#63621045::GetResponse() 
System.Net Information: 0 : [2440] FtpWebRequest#63621045::GetResponse(Method=SIZE.) 
System.Net Information: 0 : [2440] FtpControlStream#44374744 - Created connection from ***.**.***.**:***** to **.**.**.**:**. 
System.Net Information: 0 : [2440] Associating FtpWebRequest#63621045 with FtpControlStream#44374744 
System.Net Information: 0 : [2440] FtpControlStream#44374744 - Received response [220 Microsoft FTP Service] 
System.Net Information: 0 : [2440] FtpControlStream#44374744 - Sending command [USER ******] 
System.Net Information: 0 : [2440] FtpControlStream#44374744 - Received response [331 Password required for cashipftp.] 
System.Net Information: 0 : [2440] FtpControlStream#44374744 - Sending command [PASS ********] 
System.Net Information: 0 : [2440] FtpControlStream#44374744 - Received response [230 User logged in.] 
System.Net Information: 0 : [2440] FtpControlStream#44374744 - Sending command [OPTS utf8 on] 
System.Net Information: 0 : [2440] FtpControlStream#44374744 - Received response [200 OPTS UTF8 command successful - UTF8 encoding now ON.] 
System.Net Information: 0 : [2440] FtpControlStream#44374744 - Sending command [PWD] 
System.Net Information: 0 : [2440] FtpControlStream#44374744 - Received response [257 "/" is current directory.] 
System.Net Information: 0 : [2440] FtpControlStream#44374744 - Sending command [SIZE Superintendents/MSK/Stock Keeper_be.zip] 
System.Net Information: 0 : [2440] FtpControlStream#44374744 - Received response [213 96601015] 
System.Net Information: 0 : [2440] FtpControlStream#44374744 - Sending command [QUIT] 
System.Net Information: 0 : [2440] FtpControlStream#44374744 - Received response [221 Goodbye.] 
System.Net Information: 0 : [2440] FtpWebRequest#63621045::(Releasing FTP connection#44374744.) 
System.Net Verbose: 0 : [2440] Exiting FtpWebRequest#63621045::GetResponse() 
System.Net Verbose: 0 : [2440] FtpWebResponse#50706457::Close() 
System.Net Verbose: 0 : [2440] Exiting FtpWebResponse#50706457::Close() 
System.Net Verbose: 0 : [2440] WebRequest::Create(ftp://ftp.******.com/) 
System.Net Information: 0 : [2440] FtpWebRequest#89223::.ctor(ftp://ftp.*****.com/) 
System.Net Verbose: 0 : [2440] Exiting WebRequest::Create()  -> FtpWebRequest#89223 
System.Net Verbose: 0 : [2440] FtpWebRequest#89223::GetResponse() 
System.Net Information: 0 : [2440] FtpWebRequest#89223::GetResponse(Method=RETR.) 
System.Net Information: 0 : [2440] FtpControlStream#4015056 - Created connection from ***.**.***.**:***** to **.**.**.**:**. 
System.Net Information: 0 : [2440] Associating FtpWebRequest#89223 with FtpControlStream#4015056 
System.Net Information: 0 : [2440] FtpControlStream#4015056 - Received response [220 Microsoft FTP Service] 
System.Net Information: 0 : [2440] FtpControlStream#4015056 - Sending command [USER ******] 
System.Net Information: 0 : [2440] FtpControlStream#4015056 - Received response [331 Password required for cashipftp.] 
System.Net Information: 0 : [2440] FtpControlStream#4015056 - Sending command [PASS ********] 
System.Net Information: 0 : [2440] FtpControlStream#4015056 - Received response [230 User logged in.] 
System.Net Information: 0 : [2440] FtpControlStream#4015056 - Sending command [OPTS utf8 on] 
System.Net Information: 0 : [2440] FtpControlStream#4015056 - Received response [200 OPTS UTF8 command successful - UTF8 encoding now ON.] 
System.Net Information: 0 : [2440] FtpControlStream#4015056 - Sending command [PWD] 
System.Net Information: 0 : [2440] FtpControlStream#4015056 - Received response [257 "/" is current directory.] 
System.Net Information: 0 : [2440] FtpControlStream#4015056 - Sending command [TYPE I] 
System.Net Information: 0 : [2440] FtpControlStream#4015056 - Received response [200 Type set to I.] 
System.Net Information: 0 : [2440] FtpControlStream#4015056 - Sending command [PASV] 
System.Net Information: 0 : [2440] FtpControlStream#4015056 - Received response [227 Entering Passive Mode (77,44,60,82,106,69).] 
System.Net Information: 0 : [2440] FtpControlStream#4015056 - Sending command [RETR *****] 
System.Net Information: 0 : [2440] FtpControlStream#4015056 - Received response [125 Data connection already open; Transfer starting.] 
System.Net Verbose: 0 : [2440] Exiting FtpWebRequest#89223::GetResponse() 
System.Net Information: 0 : [1312] ServicePoint#42865679 - Closed as idle. 
System.Net.Sockets Error: 0 : [2440] Socket#10316078::UpdateStatusAfterSocketError() - TimedOut 
System.Net.Sockets Error: 0 : [2440] Exception in Socket#10316078::Receive - A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. 
System.Net Information: 0 : [2440] FtpWebRequest#89223::(Releasing FTP connection#4015056.) 
System.Net Verbose: 0 : [2440] FtpWebResponse#19201658::Close() 
System.Net Verbose: 0 : [2440] Exiting FtpWebResponse#19201658::Close() 

EDIT 19/04/2012: Я дал WIRESHARK идти с FTP-фильтр, и я, возможно, раскрыл некоторую информацию, которую я также не знаю, куда идти ...

EDIT: Новая информация ... Я нашел информацию на другом форуме, который проливает немного больше света, но все же не дает ответа ... Похоже, размер файла не имеет значения. Тот же эффект загружает небольшой файл, но спящий поток в цикле, чтобы продлить время загрузки. Кажется, что любая операция дольше, чем х времени (другое сообщение учитывает 100), достигнет конца и сразу же тайм-аута. Также я заметил, что, пройдя через отладчик, общая сумма полученных байтов равна размеру файла, поэтому он точно так же, как пытается прочитать последний файл, только чтобы найти, что нет никого, кроме того, что он никогда не узнает, потому что сервер никогда говорит! END EDIT

Сервер ftp должен отвечать на 226 - Закрытие соединения данных. Запрашивается действие файла успешно (например, передача файла или прерывание файла).

Однако, когда я использовал wirehark, я вижу, что это не происходит с [TCP Retransmission] перед ним. Не уверен, что это ... все еще googling. Но я уверен, что это имеет значение.

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

я пытался много разных вещей:

  • Keep-жив = ложь
  • SetPointManager.MaxIdleTime
  • Увеличение таймаута

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

EDIT 20/04/2012: Это не работает нормально с filezilla (или проводником). Я попытался загрузить с ftp с помощью explorer и получил сообщение о том, что операция была отключена. Filezilla загружает файл, а затем отключается, но он умно повторяет команду REST. Я подозреваю, что реализация этого может быть идеальной душой, поэтому я хочу понять это. Будет пост в качестве ответа, если мне удастся. END EDIT

Следует отметить, что до передачи WebException доступ к загруженному файлу блокируется. Таким образом, в случае WebClient, который я не могу повлиять на тайм-ауты, он будет просто висеть на 100% в течение длительного времени. а затем выбросить исключение. Если я установил тайм-аут FtpRequest равным 1000 и обработаю исключение, файл, как представляется, полностью загрузился, и я могу извлечь его без какого-либо повреждения.

Если у кого-нибудь есть подсказки или указатели, или даже лучшее решение :) Я был бы очень благодарен. Все входные данные будут приняты.

Спасибо

P.S Я попытался предоставить как можно больше информации, насколько это возможно, но если вам нужно больше, дайте мне знать.

+0

Связанный: [FTPWebRequest нарушен] (http://mattmitchell.com.au/ftpwebrequest-is-broken/). Я тоже сталкиваюсь с этой проблемой. Если я делаю 'netstat', я вижу тысячи открытых подключений, даже если я немедленно отдаю ответ, а' keepalive' - 'false'. Если вы посмотрите в исходном источнике .NET для 'FTPWebRequest', похоже, что он предназначен для преднамеренного закрытия соединений в надежде, что эти порты будут повторно использоваться, но на самом деле он использует каждый другой порт ... – jrh

+0

.. моя нынешняя теория заключается в том, что она каждый раз пытается использовать другой порт, пока сервер не начнет отклонять соединения. Я написал программу, которая отправляет огромное количество файлов для проверки проблемы. Он может буквально исчерпывать номера портов, netstat показывает порты, идущие от 49157 до 65535. Обратите внимание, что я отправляю только один файл за раз. – jrh

ответ

0

Попробуйте найти, если конфигурация исходного приложения ограничивает размер загрузки.

+0

Если вы имеете в виду в app.config? Все, что есть в банкомате, - это трассировка и несколько настроек. Я прочитал о настройках httpRuntime с этим эффектом, но это FTP. Есть ли аналогичные настройки, которые я могу изменить? –

 Смежные вопросы

  • Нет связанных вопросов^_^