World is now on Opti ID! Learn more

KhurramKhang
Dec 10, 2014
  2632
(0 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

Please login to comment.
Latest blogs
Make Global Assets Site- and Language-Aware at Indexing Time

I had a support case the other day with a question around search on global assets on a multisite. This is the result of that investigation. This co...

dada | Jun 26, 2025

The remote server returned an error: (400) Bad Request – when configuring Azure Storage for an older Optimizely CMS site

How to fix a strange issue that occurred when I moved editor-uploaded files for some old Optimizely CMS 11 solutions to Azure Storage.

Tomas Hensrud Gulla | Jun 26, 2025 |

Enable Opal AI for your Optimizely products

Learn how to enable Opal AI, and meet your infinite workforce.

Tomas Hensrud Gulla | Jun 25, 2025 |

Deploying to Optimizely Frontend Hosting: A Practical Guide

Optimizely Frontend Hosting is a cloud-based solution for deploying headless frontend applications - currently supporting only Next.js projects. It...

Szymon Uryga | Jun 25, 2025

World on Opti ID

We're excited to announce that world.optimizely.com is now integrated with Opti ID! What does this mean for you? New Users:  You can now log in wit...

Patrick Lam | Jun 22, 2025

Avoid Scandinavian Letters in File Names in Optimizely CMS

Discover how Scandinavian letters in file names can break media in Optimizely CMS—and learn a simple code fix to automatically sanitize uploads for...

Henning Sjørbotten | Jun 19, 2025 |