I'm trying to create a zip archive from memory stream and when I download it from my API on the web-side it tells me the archive is corrupt when I try to open it (and not much else, the download itself is successful).
This is the code I use for generating the zip-archive:
public byte[] ZipFiles(IEnumerable<FileContentResult> filesToZip)
{
var outputMemoryStream = new MemoryStream();
var zipStream = new ZipOutputStream(outputMemoryStream);
zipStream.SetLevel(3);
foreach (var fileToZip in filesToZip)
{
var inputMemoryStream = new MemoryStream(fileToZip.FileContents);
var zipEntry = new ZipEntry(fileToZip.FileDownloadName);
zipEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(zipEntry);
StreamUtils.Copy(inputMemoryStream, zipStream, new byte[4096]);
zipStream.CloseEntry();
}
zipStream.IsStreamOwner = false;
zipStream.Close();
outputMemoryStream.Position = 0;
return outputMemoryStream.ToArray();
}
It returns the zip file as a byte array, which is then put into another filecontentresult before being returned from the API (I've tried setting contenttype to both application/octet-stream and application/zip). I've seen and tried a huge amount of different solutions here on stackoverflow, but all of them seem to fail when trying to open the downloaded file. I'm using SharpZipLib. Anyone got any pointers?
Edit/new info:
After further testing/debugging, it seems like the zip file itself is okay. If I save it to the server disk I'm able to open/unpack the files. However, the action of putting it into a filecontentresult and returning it from the controller & downloading it on a client seems to break it. The file name is okay, with a .zip extension, and as mentioned I've tried both application/octet-stream and application/zip as contenttype (I think the second is is correct to use). We do already return and download other files from the API just fine, it's just zip-files that are somehow not working correctly here.
If I'm not mistaken,
outputMemoryStream.Position = 0is not enough since you don’t have a reference of the initial position and the current one. So, before the return of the function, you have to move the pointer of thememorystreamat the very start. For that, replaceoutputMemoryStream.Position = 0withoutputMemoryStream.Seek(0, SeekOrigin.Begin).