In order to change file's download name, you can add a handler to media:request
event.
It catches all media requests, including requests for pdf files.
In the handler you can modify Content-Disposition
header to contain item display name + file extension.
Similarly to how it is shown in the example you have linked, you can take advantage of HttpResponse.AddOnSendingHeaders
method to change the header value. The method is used to register a callback that the ASP.NET runtime will invoke immediately before response headers are sent for this request.
The code below was tested and it works to change file's download name for pdf files, as well as other media files and images. It is important to set conditions in the handler to run it only when it is needed, depending on what are the requirements. For example, you would definitely want to prevent this handler from being executed for shell
site, otherwise it might trigger downloading of media files when you open media items in Sitecore Content Editor. Additionally, you might want to run it only for certain file types (e.g. pdf) or only if there is a certain query string parameter is present. Please check this blog post from Anders Laub.
A display name and a file extension can be retrieved from the corresponding properties of MediaItem
:
using Sitecore.Data.Items;
using Sitecore.Events;
using Sitecore.Resources.Media;
using System;
using System.Web;
namespace CustomMediaEventHandlers
{
public class ChangeFileNameEventHandler
{
public void OnMediaRequest(object sender, EventArgs args)
{
// must apply strict conditions here in order not to invoke it unnecessarily;
// e.g. exclude shell site, invoke only for pdf files or only if a certain query string parameter is present
if (Sitecore.Context.Site.Name.Equals(Sitecore.Constants.ShellSiteName, StringComparison.OrdinalIgnoreCase))
{
return;
}
SitecoreEventArgs eventArgs = args as SitecoreEventArgs;
if (!(eventArgs?.Parameters?[0] is MediaRequest mediaRequest))
{
return;
}
MediaItem mediaItem = MediaManager.GetMedia(mediaRequest.MediaUri).MediaData.MediaItem;
if (mediaItem == null || !IsPdfRequest(mediaItem))
{
return;
}
HttpRequest request = mediaRequest.InnerRequest;
request.RequestContext.HttpContext.Response.AddOnSendingHeaders(context =>
{
context.Response.Headers["Content-Disposition"] = string.Format(
"attachment; filename={0}.{1}",
mediaItem.DisplayName,
mediaItem.Extension);
});
}
private static bool IsPdfRequest(MediaItem mediaItem)
{
return mediaItem.Extension.Equals("pdf", StringComparison.OrdinalIgnoreCase)
|| mediaItem.MimeType.Equals("application/pdf", StringComparison.OrdinalIgnoreCase);
}
}
}
Note: If you have tried a similar approach and the event handler was not invoked, it can happen when a browser cached the file and it does not make a request to the server.
Please be aware that when using Chrome, clearing site data (cache storage and application cache) from Dev tools panel will not have an effect on disk cache
. In the Network tab, Size column, it will still show 'from disk cache'
and in the request headers it will say "Provisional headers are shown" because it did not do an actual request to the server. If this is the case, you can try using an Incognito mode or a different browser or just clean cached images and files (Ctrl + Shift + Del).
Having Sitecore Media Caching
enabled (that stores media cache on the file system, /App_Data/MediaCache
, by default) does not have the same effect as browser caching, so you should check only whether it is cached in a browser or not.
Using the code above, file's download name (Content-Disposition name ) will be the item's Display Name
:
Update:
You can subscribe the handler to media:request
event by using this patch:
<?xml version="1.0" encoding="utf-8"?>
<!--
Purpose: This include file implements logic to change file name to item's display name when downloading media.
It changes response Content-Disposition header.
-->
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/">
<sitecore>
<events>
<event name="media:request">
<handler patch:after="*[@type='Sitecore.Analytics.Media.MediaRequestEventHandler, Sitecore.Analytics']"
type="CustomMediaEventHandlers.ChangeFileNameEventHandler, CustomMediaEventHandlers"
method="OnMediaRequest" />
</event>
</events>
</sitecore>
</configuration>