Sitecore

Delivering Sitecore Media Items as a Compressed ZIP

We'll Crack Through This Code Tonight

The task at hand

At some point as a developer, you might need to combine multiple Sitecore Media Library items into a compressed ZIP and deliver it on the fly to the end-user. In my use case, I had a client that wanted to build out an asset library for the press to use when creating print and online news stories.  They wanted to give their users a way to download all of the images for a given press release in one click.  In this post, I’ll document how I approached that task using a custom route in .NET supported by an ActionResult in a Controller.

In my scenario, I had a Sitecore item that has a list of images attached to it. My goal was to take that list and create a zip file out of it. Even though I was using a list that allowed for easy updating in the UI, if we switch over to raw values we’ll see something similar to this:

Imagerawvalues

Sitecore is combining the items in the list and concatenates them together with a pipe for separation between the GUIDs. Knowing this, we can target that field and do a split on the pipe. From there we can go on about the work of packing up the files. The first step for me was to create a new handler that would be able to take an ID of an item and then parse out that field so I knew which items to package up.

Creating a custom Route and ActionResult

Sitecore - Understanding Development Approaches: A Sitecore Outlook
Understanding Development Approaches: A Sitecore Outlook

Designing, building, and implementing top-notch experiences not only requires a great deal of planning, strategy, and time – it also requires the right digital experience platform (DXP) and the right development approach for your business needs.

Get the Guide

Here’s an example of a custom route to a controller action:

routes.MapRoute("Download", "download /{ItemId}", new { controller = "Media", action = "Download" }, new string[] { @"MySite.Controllers" });

Then in my controller I can create an ActionResult to get the values we’re looking to work with:

public ActionResult Download(string itemId)
{
    var parentItem = _scHelper.GetItem(itemId);
    var imageItems = parentItem.Fields[“YOUR_FIELD_GUID”].Value.Split('|');
    return Content(“OK”);
}

We’re only returning a string at this point, but we’ve got the code in place to know which items we’d like to work with. We can then do a foreach for the imageItems variable to retrieve the data we need from the MediaManager and add it to the zip file we’re creating. First, we’ll want to create a MemoryStream for us to work with, and then using that stream we can create a ZipArchive for our files.

Creating the Memory Stream and ZIP file

Here’s how we can create a MemoryStream, add a ZIP file within it, and return it as a file:

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))
    {
        // We can add our files here
    }

    // Create a byte array to convert our stream to
    Byte[] bytes = zipStream.ToArray();

    // Deliver the array as a file
    return File(bytes, "application/zip", "YourCompressedFile.zip");
}

Including the files we want in our ZIP

At this point we know which files we want to include and we have a blank ZIP file. All that’s left is for us to do is to loop through the list of images, retrieve their data from Sitecore, and include them in the ZIP file that we’re building.

We can retrieve the data for the images with the MediaManager in Sitecore:

foreach (var image in imageItems)
{
    var mediaItem = (MediaItem)_scHelper.GetItem(image);
    var media = MediaManager.GetMedia(mediaItem);
    var stream = media.GetStream().Stream;
    var extension = mediaItem.Extension;

    if (String.IsNullOrEmpty(extension)) continue;

    ZipArchiveEntry zipItem = zip.CreateEntry(mediaItem.Name + "." + extension);

    using (System.IO.Stream entryStream = zipItem.Open())
    {
        stream.CopyTo(entryStream);
    }
}

It’s that easy! The code should probably be updated to add a bit of error handling and you’ll probably want a better name than YourCompressedFile.zip as the name of your file. Hopefully this has given you an idea of how you can take advantage of raw values and the MediaManager in Sitecore to save your users a some time by being able to download a single file instead of multiple downloads.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Dave Ambrose

Dave has spent more than 20 years developing software for the web and has been working with Sitecore since 2015 with his first certification in 2016. In his spare time, he enjoys time with his family as well as golf, racing, and being the coordinator for a High School VEX Robotics program.

More from this Author

Subscribe to the Weekly Blog Digest:

Sign Up
Follow Us
TwitterLinkedinFacebookYoutubeInstagram