Zip file downloaded from memory stream is empty/invalid

784 views Asked by At

I'm trying to create a tool that takes images on my server, and downloads them to the user in a zip file. These images are Sitecore media items, that I'm getting the Stream from, and trying to copy the streams to a zip file.

        using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream())
        {
            System.IO.Compression.ZipArchive zip = new System.IO.Compression.ZipArchive(memoryStream, System.IO.Compression.ZipArchiveMode.Create, true);

            foreach (var image in imageItems)
            {
                try
                {
                    var mediaItem = (MediaItem)image;
                    var media = MediaManager.GetMedia(mediaItem);
                    Stream stream = media.GetStream();

                    var extension = mediaItem.Extension;
                    if (String.IsNullOrEmpty(extension)) continue;

                    System.IO.Compression.ZipArchiveEntry zipItem = zip.CreateEntry(image.Name + "." + extension);
                    using (System.IO.Stream entryStream = zipItem.Open())
                    {
                        stream.CopyTo(entryStream);
                    }

                }
                catch (Exception ex) { }
            }

            var bytesInStream = memoryStream.ToArray();
            Response.Clear();
            Response.ContentType = "application/force-download";
            Response.AddHeader("content-disposition", "attachment; filename=SitecoreMediaDownload.zip");
            Response.BinaryWrite(bytesInStream);
            Response.End();

The code works without any errors and I checked while debugging that bytesInStream is populated (not empty), but when I try to open/extract the zip file it says it's invalid.

2

There are 2 answers

1
Erica Stockwell-Alpert On

Figured it out - the ZipArchive has to be disposed

        using (System.IO.MemoryStream zipStream = new System.IO.MemoryStream())
        {
            using (System.IO.Compression.ZipArchive zip = new System.IO.Compression.ZipArchive(zipStream, System.IO.Compression.ZipArchiveMode.Create, true))
            {
                foreach (var image in imageItems)
                {
                    try
                    {
                        var mediaItem = (MediaItem)image;
                        var media = MediaManager.GetMedia(mediaItem);
                        var stream = media.GetStream().Stream;

                        var extension = mediaItem.Extension;
                        if (String.IsNullOrEmpty(extension)) continue;

                        System.IO.Compression.ZipArchiveEntry zipItem = zip.CreateEntry(image.Name + "." + extension);
                        using (System.IO.Stream entryStream = zipItem.Open())
                        {
                            stream.CopyTo(entryStream);
                            imagesDownloaded++;
                        }

                    }
                    catch (Exception ex) { }
                }
            }

            zipStream.Position = 0;
            litMediaExportOutput.Text = imagesDownloaded + " images downloaded";

            Response.Clear();
            Response.ContentType = "application/x-zip-compressed";
            Response.AddHeader("Content-Disposition", "attachment; filename=SitecoreMediaDownload.zip");
            Response.BinaryWrite(zipStream.ToArray());
            Response.Flush();
            Response.Close();
        }
0
Isambard Dev iwa On

Yes setting the stream back to position 0 is very important because if it is still pointing at the end of the stream then there is nothing left to read. Here is a blog about the issue as well: https://isambarddev.wordpress.com/2016/10/06/inputstreams/