0

My website has so many pdf files and for some, I need to open the pdf file on the browser and for some, I need to download. I have got some solution i.e configuration in sitecore.config file but this change reflects for all the pdf files.

Please give some solution if any.
Thanks in advance.

1

One possible solution is to create a new template _MediaHeaders with a checkbox field Content Disposition Inline:

enter image description here

and extend File template with it:

enter image description here

Then you have to overwrite MediaRequestHandler in the following way:

public class MediaRequestHandler : Sitecore.Resources.Media.MediaRequestHandler
{
    private void SetContentDispositionHeaders(HttpContext context, Sitecore.Resources.Media.Media media)
    {
        if (media.MediaData.MediaItem.InnerItem[Constants.Templates.MediaHeaders.Fields.ContentDispositionInline.ID] == "1")
        {
            var extension = media.Extension;
            if (extension.Length > 0 && extension[0] != '.')
            {
                extension = "." + extension;
            }

            var fileName = media.MediaData.MediaItem.Name + extension;

            context.Response.Headers["Content-Disposition"] = $"inline; filename=\"{fileName}\"";
        }
    }

    protected override void SendMediaHeaders(Sitecore.Resources.Media.Media media, HttpContext context)
    {
        base.SendMediaHeaders(media, context);
        this.SetContentDispositionHeaders(context, media);
    }
}
  • getting error while overwriting the MediaRequesthandler....in this section [Constants.Templates.MediaHeaders.Fields.ContentDispositionInline.ID]. am i missing some reference please help? – Akash Mishra Oct 10 at 10:14
  • Constants.Templates.MediaHeaders.Fields.ContentDispositionInline.ID - it's a const that contains the id of "Content Disposition Inline" field. Replace it with your id. – Bartłomiej Mucha Oct 10 at 12:34
  • Hi Bartłomiej, Thanks for your valuable help. Is there any another way to do it?because if i override the media handler then it will check this condition for all the media file every time. – Akash Mishra Oct 10 at 13:45
  • You can think of other ways, for example you can add some parameter to pdf link and then check this parameter in MediaRequestHandler instead of checkbox field. Above example is how I implemented it. – Bartłomiej Mucha Oct 10 at 14:21
  • Thanks #Bartłomiej Mucha for your help. – Akash Mishra Oct 10 at 14:32
1

If you don't want to overwrite MediaRequestHandler, you can achieve this using media:request event. you need to write your custom handler for this -

<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
  <sitecore>
    <events>
      <event name="media:request">
        <handler type="xyz.foundation.downloadmedia, xyz.foundation" method="OnMediaRequest"/>
      </event>
    </events>
  </sitecore>
</configuration>

This handler will check for the query string in your media request and will force the download based on it.

public void OnMediaRequest(object sender, EventArgs args)
    {
        // Check if the request was for a download, else break out early
        if (!Sitecore.MainUtil.GetBool(Sitecore.Web.WebUtil.GetQueryString("download"), false))
            return;

        // Safety checks
        if (Sitecore.Context.Site.Name.Equals(Sitecore.Constants.ShellSiteName, StringComparison.InvariantCultureIgnoreCase))
            return;
        var sitecoreEventArgs = (SitecoreEventArgs)args;
        if (sitecoreEventArgs == null || !sitecoreEventArgs.Parameters.Any())
            return;
        var request = (MediaRequest)sitecoreEventArgs.Parameters[0];
        if (request == null)
            return;

        // Now we've established we have a valid request
        ForceMediaDownload(request);
    }

    /// <summary>
    /// Forces download of the requested media item prompting the user to save the file
    /// </summary>
    /// <param name="request">The MediaRequest</param>
    private void ForceMediaDownload(MediaRequest request)
    {
        var mediaItem = MediaManager.GetMedia(request.MediaUri).MediaData.MediaItem;

        var response = request.InnerRequest.RequestContext.HttpContext.Response;
        response.Clear();
        response.ContentType = mediaItem.MimeType;
        response.Headers.Set("Content-Disposition", "attachment; filename=" + GetFileName(mediaItem));
        response.StatusCode = (int)HttpStatusCode.OK;
        response.BufferOutput = true;
        mediaItem.GetMediaStream().CopyTo(response.OutputStream);
        response.Flush();
        response.End();
    }

    private static string GetFileName(MediaItem mi)
    {
        // Some versions of IE don't like the spaces in the names Surprise!
        return ("{0}.{1}".FormatWith(mi.Name, mi.Extension)).Replace(" ", "-");
    }
}

all you need to do is ensure that the URL parameter download=1 is appended to any links you wish to force save prompt for, e.g. /-/media/Koala.jpg?download=1

reference - https://jammykam.wordpress.com/2015/11/16/force-download-of-media-files/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.