Ensuring image extension for content URLs
When using an image resizing component, like we do in the Focal Point plugin, it's really important that the file extension is there. If it's not, the resizing engine won't kick in for the request, and that enormous image is sent straight to your mobile users, and they will forever hate your guts.
I've implemented a solution using the new (in CMS 10) IUrlSegmentCreator events, and a regular InitializationModule. Code below. It uses the first registered extension for your media type as the default extension for the URL segment. This works for me, since I have separate Media types for all image files, like JpegImage, PngImage etc, to be able to more granularly control their usage, through the AllowedTypes attribute. If you have a single MediaData for all your images, I recommend altering the extension mapping to maybe use the MimeType property and get an appropriate extension based on that.
/*using System;
using System.IO;
using System.Linq;
using EPiServer;
using EPiServer.Core;
using EPiServer.Framework;
using EPiServer.Framework.DataAnnotations;
using EPiServer.Framework.Initialization;
using EPiServer.Web;
*/
[InitializableModule, ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class ImageDataInitialization : IInitializableModule {
private bool eventsAttached;
public void Initialize(InitializationEngine context) {
if(!this.eventsAttached) {
var creator = context.Locate.Advanced.GetInstance<IUrlSegmentCreator>();
creator.Created += CreatedMediaSegment;
this.eventsAttached = true;
}
}
private static void CreatedMediaSegment(object sender, UrlSegmentEventArgs e) {
var content = e.Content as ImageData;
if(content != null) {
var extension = Path.GetExtension(content.RouteSegment);
if(string.IsNullOrWhiteSpace(extension)) {
var type = content.GetOriginalType();
var fileExtension = GetExtensionForType(type);
if(!string.IsNullOrWhiteSpace(fileExtension)) {
content.RouteSegment = content.RouteSegment + "." + fileExtension;
}
}
}
}
private static string GetExtensionForType(Type contentType) {
var mediaDescriptorAttribute = contentType?.GetCustomAttributes(typeof(MediaDescriptorAttribute), false).OfType<MediaDescriptorAttribute>().FirstOrDefault();
return mediaDescriptorAttribute?.Extensions?.FirstOrDefault();
}
public void Uninitialize(InitializationEngine context) {
var creator = context.Locate.Advanced.GetInstance<IUrlSegmentCreator>();
creator.Created -= CreatedMediaSegment;
this.eventsAttached = false;
}
}
Comments