14

Currently, when a user clicks on a PDF link on my site (served from the Media Library), the browser will download the PDF file. I'd like to change the behavior from downloading to opening in browser (I am aware that users can change their browser settings to force the behavior they want; I want to change the default behavior).

I know that I need to change the Content-Disposition response header to have inline; instead of attachment;. I could write a pipeline processor to change the Content-Disposition header, but I was hoping Sitecore had a setting for this specific behavior.

My site is currently on Sitecore 8.2 rev 161221.

  • I'm trying to reach a similar result to yours, but I'm currently unable to show the PDF link, I'm using Sitecore 9 and SXA 1.7, so i'm using rendering variants to show the pdf fields, but since the field type for the file is "File", it doesn't show anything on the page.. any advice on how to show that? – Mie ElMansy Jun 27 '18 at 12:35
20

The <mediaLibrary><mediaTypes> section of Sitecore.config (or web.config in older versions of Sitecore) contains a <mediatype> element for each file type. Within each mediatype element is a <forceDownload> element. The Content-Disposition header will be set according to the value of the forceDownload setting; attachment; for true, inline; for false.

By default, forceDownload is set to true for PDFs. Changing this value to false will instruct browsers to view the file instead of download.

  • 2
    If you do this and it's still not working, make sure the line <mediaType extensions="pdf"><mimeType>application/pdf</mimeType></mediaType> exists, and is not commented out in your app_config/Mimetypes.config – GoetzOnline Jun 8 '17 at 16:19
  • Any way to do this on a per file basis? – Zachary Dow Nov 30 '17 at 21:20
  • @ZacharyDow: I've not tried this, but you could probably use a custom pipeline to change the response headers before the media item response is sent. – Ed Schwehm Nov 30 '17 at 23:56
  • @ZacharyDow please read my answer where I provided a simple solution to do this on a per file basis – Bartłomiej Mucha Oct 3 '18 at 7:06
  • 1
    It works with Sitecore 9.0.1 - Update 2 too. Thanks! – Dash Dec 20 '19 at 3:29
4

You can also easily extend Sitecore to set Content-Disposition per file. To do this, add a new field on File template, located here /sitecore/templates/System/Media/Versioned/File. The best way is to create a new template and make File template to inherit from it.

The new field can be a checkbox named: Set Content Disposition Inline.

Then you have to create your own MediaRequestHandler and set it in Web.config. You can do that with transform file like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.webServer>
    <handlers>
      <add verb="*" path="sitecore_media.ashx" type="YourNamespace.MediaRequestHandler, AssemblyName" name="Sitecore.MediaRequestHandler" xdt:Transform="SetAttributes(type)" xdt:Locator="Match(name)" />
    </handlers>
  </system.webServer>
</configuration>

The last piece of course is MediaRequestHandler. You have to create a new class and inherit from existing one. This is how your class can looks like:

public class MediaRequestHandler : Sitecore.Resources.Media.MediaRequestHandler
{
    protected override bool DoProcessRequest(HttpContext context, MediaRequest request, Sitecore.Resources.Media.Media media)
    {
        if (base.DoProcessRequest(context, request, media))
        {
            if (context.Response.StatusCode != 304)
            {
                if (media.MediaData.MediaItem.InnerItem[setContentDispositionFieldId] == "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}\"";
                }
            }

            return true;
        }

        return false;
    }
}
  • 1
    Don't do this! base.DoProcessRequest sends the request so you can't modify the request headers after calling base.DoProcessRequest. If you have a decompiler you can see what I am referring to. – Timothy Gonzalez Apr 26 '19 at 21:07

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.