A critical vulnerability was discovered in React Server Components (Next.js). Our systems remain protected but we advise to update packages to newest version. Learn More

K Khan
Dec 10, 2014
  6036
(5 votes)

Using Blobs and CDN both effectively

We have a requirement where Editors can upload images on cloud and use those from website.

We implemented a blob provider to let editors upload and use their images on cloud (cloudinary.com) http://world.episerver.com/code/K-Khan-/Cloudinary-Implementation-in-Blob/

But there were few issues with this implementation, as on presenting the images on website in OpenRead function of provider, we have to download this images in Memory. To read image in memory. That means extra bandwidth usage and using server resources unnecessary. Another option was to redirect to CDN in provider. That means a 302 status and a Error in log files (http://world.episerver.com/Modules/Forum/Pages/Thread.aspx?id=113925). With redirection we have another issue that In Online centre Catalog module was not able to prepare thumbnails.

To deal with these issues we solved it by translating images from globalassets/image.jpg to direct CDN url http://res.cdn.com/account/1537157355371237123.jpg and for Editors we kept the original implementation. This can be useful in many other cases also.

Requirement:
Change <img src="/globalassets/logo.png" alt="" class="" itemprop="logo"> to url in cdn <img src=http://res.cloudinary.com/example.png alt="" class="" itemprop="">

Solution:
I got the help of Johan's solution in some forum post he advised. In initialization module overload ContentRoute.CreatedVirtualPath

ContentRoute.CreatedVirtualPath += this.ReplaceWithCloudUrl;
CatalogRouteHelper.MapDefaultHierarchialRouter(RouteTable.Routes, true);

public void ReplaceWithCloudUrl(object source, UrlBuilderEventArgs eventArgs)
        {
            var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();

            ////Check if routed content is a IBinaryStorable with a Cloudinary Blob, if so replace url with cdn blob uri      
            object contentReferenceObject;
            if (eventArgs.RouteValues.TryGetValue(RoutingConstants.NodeKey, out contentReferenceObject))
            {
                ContentReference routedContentLink = contentReferenceObject as ContentReference;
                if (!ContentReference.IsNullOrEmpty(routedContentLink))
                {
                    var binaryContent = contentLoader.Get<IContent>(routedContentLink) as IBinaryStorable;
                    if (binaryContent != null)
                    {
                        ////Check that Everyone has Read access before switching to external url
                        ISecurable securable = binaryContent as ISecurable;
                        if (securable != null)
                        {
                            if ((securable.GetSecurityDescriptor().GetAccessLevel(PrincipalInfo.AnonymousPrincipal) & AccessLevel.Read) != AccessLevel.Read)
                            {
                                return;
                            }
                        }

                        var cloudinaryBlob = binaryContent.BinaryData as CloudinaryFileBlob;
                        var httpContext = System.Web.HttpContext.Current.GetRequestContext().HttpContext;
                        if (cloudinaryBlob != null && (!httpContext.Request.Path.ToLower().Contains(SiteConstants.EditingUrlPart.AppSetting())))
                        {
                            imagePath = //CDN Image Path that Blob;
                           
                            UrlBuilder cdnUrlBuilder = new UrlBuilder(imagePath);
                            eventArgs.UrlBuilder.Uri = cdnUrlBuilder.Uri;
                        }
                    }
                }
            }
        }

Dec 10, 2014

Comments

K Khan
K Khan Dec 10, 2014 06:57 PM

Will be happy to hear, how other tech masters resolved this type of issues?

Dec 10, 2014 08:40 PM

This is awesome. This is how blobs should be served!

Frederik Vig
Frederik Vig Dec 10, 2014 09:39 PM

We´ve done similar, but instead we´ve used the IIS extension URL Rewrite to rewrite ouput URLs to the CDN version. The CDN adds the image cached, if it didn´t have the image it would contact EPiServer and get the right image, then put it in it´s cache and serve it to the end user. Like a reverse proxy basically.

Frederik

Please login to comment.
Latest blogs
Building simple Opal tools for product search and content creation

Optimizely Opal tools make it easy for AI agents to call your APIs – in this post we’ll build a small ASP.NET host that exposes two of them: one fo...

Pär Wissmark | Dec 13, 2025 |

CMS Audiences - check all usage

Sometimes you want to check if an Audience from your CMS (former Visitor Group) has been used by which page(and which version of that page) Then yo...

Tuan Anh Hoang | Dec 12, 2025

Data Imports in Optimizely: Part 2 - Query data efficiently

One of the more time consuming parts of an import is looking up data to update. Naively, it is possible to use the PageCriteriaQueryService to quer...

Matt FitzGerald-Chamberlain | Dec 11, 2025 |

Beginner's Guide for Optimizely Backend Developers

Developing with Optimizely (formerly Episerver) requires more than just technical know‑how. It’s about respecting the editor’s perspective, ensurin...

MilosR | Dec 10, 2025