FtpWebRequest Скачать файл неверного размера - PullRequest
3 голосов
/ 07 июля 2010

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

        FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverPath);

        request.KeepAlive = true;
        request.UsePassive = true;
        request.UseBinary = true;

        request.Method = WebRequestMethods.Ftp.DownloadFile;
        request.Credentials = new NetworkCredential(userName, password);                

        using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
        using (Stream responseStream = response.GetResponseStream())
        using (StreamReader reader = new StreamReader(responseStream))
        using (StreamWriter destination = new StreamWriter(destinationFile))
        {
            destination.Write(reader.ReadToEnd());
            destination.Flush();
        }

Файл, который я загружаю, является dll, и моя проблема в том, что он изменяетсяпроцесс в некотором роде.Я знаю это, потому что размер файла увеличивается.У меня есть подозрение, что этот раздел кода виноват:

        destination.Write(reader.ReadToEnd());
        destination.Flush();

Может кто-нибудь предложить какие-либо идеи относительно того, что может быть не так?

1 Ответ

11 голосов
/ 08 июля 2010

StreamReader и StreamWriter работают с символьными данными, поэтому вы декодируете поток из байтов в символы, а затем снова кодируете его обратно в байты.Файл dll содержит двоичные данные, поэтому такое преобразование в оба конца приведет к ошибкам.Вы хотите прочитать байты непосредственно из объекта responseStream и записать в FileStream, который не обернут в StreamWriter.

Если вы используете .NET 4.0, вы можете использовать Stream.CopyTo, но в противном случае вам придется скопировать поток вручную. Этот вопрос StackOverflow имеет хороший метод для копирования потоков:

public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[32768];
    while (true)
    {
        int read = input.Read(buffer, 0, buffer.Length);
        if (read <= 0)
            return;
        output.Write(buffer, 0, read);
    }
}

Итак, ваш код будет выглядеть так:

using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
using (FileStream destination = File.Create(destinationFile))
{
    CopyStream(responseStream, destination);
}
...