Sitecore Custom Media Request Handler to perform image name translation

Background: We have a client that uses inRiver as Product Information Management system. inRiver has a adapter for Sitecore that connects Sitecore to inRiver. The adapter works by creating and updating Sitecore items for Products, Categories, Images, etc. from the PIM. All Sitecore items created by the adapter have a name which has Ids from inRriver. For example a category image would have a name of 139442-720 and display name of 23475_CAT_0.jpg.

Problem: When referring to these images from the website we were in a way forced to use the name instead of the display name because Sitecore media request handler cannot lookup images by display name. We needed to be able to refer to the images using /-/media/inriver/23475_CAT_0.jpg instead of /-/media/inriver/139442-720

Solution: What we needed in essence is a custom Media Request Handler that would translate from the Display Name to the Item Name, retrieve the media stream and send the response to the browser. We decided to use the Solr index to do the lookup instead of using the Sitecore API for speed. We have an index that indexes the inriver media sitecore items. Now we can query this index using the DisplayName and get the Id based Item name back. Once we have the item name we can get the media using Sitecore MediaManager. After that its just a matter of copying the stream to the Response stream.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
public class CustomMediaRequestHandler : MediaRequestHandler
    {
        public override void ProcessRequest(HttpContext context)
        {
            if (context.Request.Path.ToLower().Contains("/media/inriver/"))
            {
                var requestedFilename = Path.GetFileName(context.Request.Url.LocalPath);

                //we want to fallback to regular sitecore media handler if we don't need to do the translation
                if (!Regex.Match(requestedFilename, @"^\d{3,8}-\d{3,8}\.([a-z]|[A-Z]){2,4}$", RegexOptions.Compiled | RegexOptions.IgnoreCase).Success)
                {
                    var mediaItem = SearchHelper.GetMediaItemByResourceDisplayName(Path.GetFileNameWithoutExtension(requestedFilename), requestedFilename);

                    if (mediaItem == null)
                    {
                        Log.Warn("Can't find media item for url: " + context.Request.Url.LocalPath, this);
                    }

                    if (mediaItem != null)
                    {
                        Media media = MediaManager.GetMedia(mediaItem);
                        var fileExtention = Path.GetExtension(requestedFilename).ToLower();

                        context.Response.ContentType = ReturnMimeType(fileExtention);

                        if (fileExtention == ".png" || fileExtention == ".jpg" || fileExtention == ".jpeg")
                        {
                            var mediaOptions = GetMediaOptions(context);

                            using (var mediaStream = media.GetStream(mediaOptions))
                            {
                                mediaStream.CopyTo(context.Response.OutputStream);
                            }
                        }
                        else
                        {
                            using (var mediaStream = media.GetStream())
                            {
                                mediaStream.CopyTo(context.Response.OutputStream);
                            }
                        }
                        context.Response.Cache.SetCacheability(Settings.MediaResponse.Cacheability);
                        context.Response.Cache.SetMaxAge(Settings.MediaResponse.MaxAge);
                        context.Response.Flush();
                        context.Response.End();
                    }
                }
            }
            base.ProcessRequest(context);
        }

        private static MediaOptions GetMediaOptions(HttpContext context)
        {
            var mh = context.Request.QueryString.Get("mh");
            if(string.IsNullOrWhiteSpace(mh))
            {
                mh = context.Request.QueryString.Get("h");
            }

            var mw = context.Request.QueryString.Get("mw");
            if (string.IsNullOrWhiteSpace(mw))
            {
                mw = context.Request.QueryString.Get("w");
            }

            MediaOptions mo = new MediaOptions { BackgroundColor = Color.Transparent };

            if (!string.IsNullOrWhiteSpace(mh))
            {
                mo.MaxHeight = int.Parse(mh);
            }

            if (!string.IsNullOrWhiteSpace(mw))
            {
                mo.MaxWidth = int.Parse(mw);
            }
            return mo;
        }

        private string ReturnMimeType(string fileExtension)
        {
            fileExtension = fileExtension ?? string.Empty;
            switch (fileExtension.ToLower())
            {
                case ".gif":
                    return "image/gif";
                case ".png":
                    return "image/png";
                case ".tiff":
                case ".tif":
                    return "image/tiff";
                case ".jpg":
                case ".jpeg":
                    return "image/jpeg";
                case ".pdf":
                    return "application/pdf";
                case ".ai":
                case ".eps":
                    return "application/postscript";
                case ".zip":
                    return "application/zip";
                default:
                    return string.Empty;
            }
        }

    }

Webmin: there are too many zones on your system to display here

I have a linux server running ubuntu 10.04 and I use webmin 1.570 to monitor and manage my services like named and mysql. Yesterday I went over the default limit of number of zones shown in the ‘Existing DNS Zones’ section of the named module on webmin and got a message “there are too many zones on your system to display here”. I really didn’t want to go the command line way of managing my zones and like to see all the zones in one place in a nice gui.
The solution was to click on the ‘Module Config’ link for the ‘BIND DNS Server’ and set the ‘Maximum number of zones to display’ to 100 and hit save.
From the main Webmin window, click Servers, then Bind DNS Server and finally Module Config

The module config link may not show for all webmin users depending on how you have it setup (you can restrict access to parts of modules from the Webmin users control). Also, I know for sure that the module config link is not available on webmin version 1.180 and older. Upgrade to 1.230 atleast and you should be able to see the link. You can upgrade webmin from the Webmin->Webmin Configuration->Upgrade Webmin section