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>' -->
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 theGZipStream
:... 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 theGZipStream
, it will corrept the data; if you call it afterwards it'll fail as theMemoryStream
is closed.) As an aside, when you do need to rewind a stream, I'd recommend usingstream.Position = 0;
as a simpler alternative.