tags:

views:

561

answers:

2

I have this method to transfer files using a FTP Server:

private void TransferNeededFiles(IEnumerable<string> filenames)
{
    foreach (var filename in filenames)
    {
     var request = WebRequest.Create(new Uri(@"ftp://{0}/{1}".Fill(Config.ServerUri, filename))) as FtpWebRequest;

     if (request != null)
     {
      request.Credentials = new NetworkCredential(Config.Username, Config.Password);

      request.Method = WebRequestMethods.Ftp.DownloadFile;
      using (var streamReader = new StreamReader(request.GetResponse().GetResponseStream()))
      {
       var fileStream = new FileStream(@"{0}/{1}".Fill(Config.DestinationFolderPath, filename), FileMode.Create);

       var writer = new StreamWriter(fileStream);
       writer.Write(streamReader.ReadToEnd());
       writer.Flush();
       writer.Close();

       fileStream.Close();
      }
     }
    }
}

A .gz file, included in the list of filenames, is always corrupted. When I try to copy from ftp using windows explorer, the file is not corrupted. Do you know what is happening?

+2  A: 

The problem is this line:

writer.Write(streamReader.ReadToEnd());

StreamReader.ReadToEnd() returns a Unicode encoded string. You want something that will read the stream byte for byte.

Joel Coehoorn
I think Joel's nailed it (as usual). You will probably want to read the stream in chunks also instead of all at once.
Josh E
A: 

Readers and Writers work with Unicode characters. To transfer binary data you want to be working with raw bytes, so you should be using plain Streams. You can copy from one stream to another with a loop like the following:

BufferedStream inputStream, outputStream;
byte[] buffer = new byte[4096];
int bytesRead;

while ((bytesRead = inputStream.Read(buffer)) > 0)
{
    outputStream.Write(buffer, 0, bytesRead);
}

A good thing about this is that it will also only use a fixed amount of memory rather than reading the entire file into memory at once.

John Kugelman