Creating a zip archive from memory stream in .Net Core

1.3k Views Asked by At

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.

1

There are 1 best solutions below

0
Ariel Navarro On

If I'm not mistaken, outputMemoryStream.Position = 0 is 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 the memorystream at the very start. For that, replace outputMemoryStream.Position = 0 with outputMemoryStream.Seek(0, SeekOrigin.Begin).