views:

49

answers:

1

I’m using the following code to download a file from a remote ftp server:

        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();
        }

The file that I’m downloading is a dll and my problem is that it is being altered by this process in some way. I know this because the file size is increasing. I have a suspicion that this section of code is at fault:

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

Can anyone offer any ideas as to what may be wrong?

+1  A: 

StreamReader and StreamWriter work with character data, so you are decoding the stream from bytes to characters and then encoding it back to bytes again. A dll file contains binary data, so this round-trip conversion will introduce errors. You want to read bytes directly from the responseStream object and write to a FileStream that isn't wrapped in a StreamWriter.

If you are using .NET 4.0 you can use Stream.CopyTo, but otherwise you will have to copy the stream manually. This StackOverflow question has a good method for copying streams:

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);
    }
}

So, your code will look like this:

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