Storing files into zip archive and download zip file http post action method and file return type in Sitecore MVC.

Prem Murmu on 1/5/2023 3:06:33 PM

Requirement: Download selected files or download all. So selected files or all files must be downloaded as a zipped file.

I am going to implement in Sitecore MVC.

Step1: I will write ajax post request that send some media data  as array to Action method

$.ajax({

                type: "POST",

                url: "/Files/BulkDownload",

                data: JSON.stringify(selectedMediaValues),

                contentType: "application/json; charset=utf-8",

                xhrFields: {

                    responseType: 'blob'

                },

                success: function (blob, status, xhr) {

                    console.log("Request processed successfully .." + status.responsetext);

                    var disposition = xhr.getResponseHeader('Content-Disposition');

                    if (disposition && disposition.indexOf('attachment') !== -1) {

                        var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;

                        var matches = filenameRegex.exec(disposition);

                        if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');

                    }

                    if (typeof window.navigator.msSaveBlob !== 'undefined') {

                        // IE workaround for "HTML7007: One or more blob URLs

//were revoked by closing the blob for which they were created.

//These URLs will no longer resolve as the data backing the URL has been freed."

                        window.navigator.msSaveBlob(blob, filename);

                    } else {

                        var URL = window.URL || window.webkitURL;

                        var downloadUrl = URL.createObjectURL(blob);

                        if (filename) {

                            // use HTML5 a[download] attribute to specify filename

                            var a = document.createElement("a");

                            // safari doesn't support this yet

                            if (typeof a.download === 'undefined') {

                                window.location.href = downloadUrl;

                            } else {

                                a.href = downloadUrl;

                                a.download = filename;

                                document.body.appendChild(a);

                                a.click();

                            }

                        } else {

                            window.location.href = downloadUrl;

                        }

                        setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup

                    }

                },

                error: function (e) {

                    alert('Something went wrong while processing your request. Please try again after sometime.');

                    console.log("ERROR : ", e.responsetext);

                }

            })


Let me explain you what i am doing in ajax call:

type: "POST" : It is post ajax post type call/action

 url: "/Files/BulkDownload": It is url to target the controller and action method i am targeting to send data from ajax. I have registered the route thats why only controller and action method name here, but if you don't register the route you can write url like "api/sitecore/{controller name}/{action method name}"

data: JSON.stringify(selectedMediaValues): Converting data to json type

contentType: "application/json; charset=utf-8": It is data type we are sending a data to target action method.

 xhrFields: { responseType: 'blob' }: It is data type we are expecting a data after response.

success: function (blob, status, xhr): It is part where we write something after response is ok or status is 200.

Script in this section is to force file download from client(browser).

What script is doing:

It is getting filename from the response header content disposition, based on it, It creating temporary link(anchor link) to download the response file.

It is script I got from Stackoverflow suggested by one of the Sitecore stackexchange's member. It is I will attach link as reference below.

What problem is solve by this script:

Returning file type response from action method in Sitecore mvc was not able to download the file or Zip file, this script helps to download the file.

Step 2. I will write http post actionresult type action method and return type zip file to download.

Code//

public ActionResult BulkDownload(string[] checkboxSelected)
    {
        string[] fileItemIDs = checkboxSelected.Distinct().ToArray();
        using (System.IO.MemoryStream zipStream = new System.IO.MemoryStream())
        {
            using (ZipArchive zip = new ZipArchive(zipStream, System.IO.Compression.ZipArchiveMode.Update, true))
            {
                foreach (var fileid in fileItemIDs)
                {
                    try
                    {
                        var lgItemID = Sitecore.Context.Database.Items.GetItem(fileid);
                        Sitecore.Data.Fields.FileField fileField = ((Sitecore.Data.Fields.FileField)lgItemID.Fields["File"]);
                        var mediaItem = fileField.MediaItem;
                        var media = MediaManager.GetMedia(mediaItem);
                        var stream = media.GetStream().Stream;
                        var extension = mediaItem.Fields["extension"].Value;
                        if (String.IsNullOrEmpty(extension)) continue;
                        ZipArchiveEntry zipItem = zip.CreateEntry(mediaItem.Name + "." + extension);
                        using (Stream entryStream = zipItem.Open())
                        {
                            stream.CopyTo(entryStream);
                        }

                    }
                    catch (Exception ex) { }
                }
            }
            byte[] fileBytes = zipStream.ToArray();
            System.Net.Mime.ContentDisposition contentDisposition = new System.Net.Mime.ContentDisposition
            {
                FileName = "Selectedfile.zip",
                Inline = false
            };
            string ContentType = System.Net.Mime.MediaTypeNames.Application.Octet;
            Response.Headers.Add("Content-Disposition", contentDisposition.ToString());
            Response.Headers.Add("X-Content-Type-Options", "nosniff");
            return File(fileBytes, ContentType);       
    }

I created post action result and File return type, which will allow to download zip file.

I am creating memory stream, initiating the ZipArchive Class.

Next putting media files&stream(after extracting the media item from sitecore file item) into zip createEnty. Zip acrchive has method to create/update new entry by method createEntry.

At last converting the Zipstream to bytes array and defining some response headers like content disposition, content type etc..

Few notable things:

Get item from ID in Sitecore:

 var lgItemID = Sitecore.Context.Database.Items.GetItem(fileid);

Get Media file Field ID in Sitecore

Sitecore.Data.Fields.FileField fileField = ((Sitecore.Data.Fields.FileField)lgItemID.Fields["File"]);

Get Media Item from media field ID in Sitecore
                        var mediaItem = fileField.MediaItem;
Media and Media stream from Media item.
                        var media = MediaManager.GetMedia(mediaItem);
                        var stream = media.GetStream().Stream;

Get Media file extension in Sitecore
var extension = mediaItem.Fields["extension"].Value;

Please find the some Reference link below:

Downloading multiple files from a server as a single zip file

Handle file download from ajax post

0 Comments on this post

Comments(0)||Login to Comments


InterServer Web Hosting and VPS
  • see more..