Lukas Dvorak
Lukas Dvorak

Reputation: 481

How to force download Sitecore media items (images)?

I need to have force download action after clicking on Sitecore media link. I didn't find any useful Sitecore advance how to achieve that.

In Sitecore configuration you can define which mime types will be force downloaded. But problem is, if you want to do it for images. Because if you do this

<mediaType name="JPEG image" extensions="jpg, jpeg, jpe">
    <mimeType>image/jpeg</mimeType>
    <forceDownload>true</forceDownload>
</mediaType>

all images will disappear because of browser won't be able to present them in HTML!

How to make all Sitecore media files force downloaded on click?

Upvotes: 4

Views: 1675

Answers (1)

Lukas Dvorak
Lukas Dvorak

Reputation: 481

After some investigation in Sitecore's code with decompiler I decide that the best way is to extend Sitecore MediaRequestHandler.

But how to recognize if I want to present an image and download an image? We have to add query string parameter to URL, something like "dl=1"

public class MediaRequestHandler : Sitecore.Resources.Media.MediaRequestHandler, System.Web.SessionState.IRequiresSessionState
{
    protected override bool DoProcessRequest(HttpContext context, MediaRequest request, Media media)
    {
        // identify query string param from requested URL
        bool isDownload = Utils.UrlUtils.HasQueryParam(context.Request.Url, "dl", "1");
        if (isDownload)
        {
            using (MediaStream stream = media.GetStream())
            {
                // we have to check if file is not already force downloaded by Sitecore
                if (!stream.ForceDownload)
                {
                    string mediaName = media.MediaData.MediaItem.Name + "." + media.MediaData.Extension;
                    context.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + mediaName + "\"");
                }
                context.Response.AddHeader("Content-Length", stream.Length.ToString());
            }
        }
        // it must be called after all logic
        return base.DoProcessRequest(context, request, media);
    }
}

Some remarks for the code:

  • all logic must be before calling original DoProcessRequest method because after processing it will flush all headers to response (!)
  • there must be query string parameter which decide if to force download file or not
  • some mime types already have "forcedownload" attribute from configuration so you have to check it to avoid duplicate header "Content-Disposition" (this cause problem in Chrome, downloaded file will have extension something like "filename-, attachment")

Upvotes: 1

Related Questions