FTP + GZipStream = 'File is broken' when unzipped

525 Views Asked by At

I am trying to use a GZipStream to compress a document prior to uploading to an FTP server. If I save the compressed file stream to disk just prior to uploading, the copy on the local file system is correct. However, when I try to unzip the file on the FTP server I get a 'File is broken' error from 7zip. The resultant unzipped file is correct until the last few characters when a sequence of characters is repeated. I have tried many different configurations to no avail.

    public static void FTPPut_Compressed(string fileContents, string ftpPutPath)
    {
      using (var inStream = new System.IO.MemoryStream(System.Text.Encoding.Default.GetBytes(fileContents)))
      {
         inStream.Seek(0, SeekOrigin.Begin);
         using (var outStream = new System.IO.MemoryStream())
         {
             using (var zipStream = new GZipStream(outStream, CompressionMode.Compress))
             {
                 inStream.CopyTo(zipStream);
                 outStream.Seek(0, SeekOrigin.Begin);
                 FTPPut(ftpPutPath, outStream.ToArray());
             }
         }
      }
    }

    private static void FTPPut(string ftpPutPath, byte[] fileContents)
    {
      FtpWebRequest request;

      request = WebRequest.Create(new Uri(string.Format(@"ftp://{0}/{1}", Constants.FTPServerAddress, ftpPutPath))) as FtpWebRequest;
      request.Method = WebRequestMethods.Ftp.UploadFile;
      request.UseBinary = true;
      request.UsePassive = true;
      request.KeepAlive = true;
      request.Credentials = new NetworkCredential(Constants.FTPUserName, Constants.FTPPassword);
      request.ContentLength = fileContents.Length;

      using (var requestStream = request.GetRequestStream())
      {
         requestStream.Write(fileContents, 0, fileContents.Length);
         requestStream.Close();
         requestStream.Flush();
      }
    }

Ex of corrupted output:

    <?xml version="1.0" encoding="utf-16"?>
        <ArrayOfCreateRMACriteria xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <CreateRMACriteria>
                <RepairOrderId xsi:nil="true" />
                <RMANumber>11-11111</RMANumber>
                <CustomerId>1111</CustomerId>
            </CreateRMACriteria>
        </ArrayOfCreateRMACriteriafriafriafriafriafriafriafriafriafriafriafriafriafriafriafriafriafria
    <!-- missing '></xml>' -->
1

There are 1 best solutions below

2
On BEST ANSWER

You're not closing (and therefore flushing) the zip stream until after you've uploaded it. I suspect that may well be the problem. Move this line to after the using statement that creates/uses/closes the GZipStream:

FTPPut(ftpPutPath, outStream.ToArray());

... and get rid of the Seek call entirely. ToArray doesn't require it, and there's no suitable point in your code to call it. (If you call it before you flush and close the GZipStream, it will corrept the data; if you call it afterwards it'll fail as the MemoryStream is closed.) As an aside, when you do need to rewind a stream, I'd recommend using stream.Position = 0; as a simpler alternative.