MediaCachePath for Multisite Site configs

MediaCachePath for Multisite Site configs

A client that I work with has taken Sitecore and extended it getting max value out of the platform. They use Sitecore to extend a few "Parent" sites into hundreds of child/member sites. This gives the member sites free content from the parent site as well as use of a full product catalog. The reason I mention the product catalog, is that there are hundreds of products with thousands of related images.

Understanding how Sitecore treats sites in the case is important. When an image is requested from an end user, the image is pull out of SQL and stored in the App_Data/MediaCache folder. If the same image is requested, but it is resized or the resolution is reduced for mobile devices, that image is stored in the media cache also. Not a big deal for a site, expected space considerations.

The issue here is that this process is repeated for every single site in Sitecore. A single 2MB file, if used by 600 sites, will now consume 1.2 GB. Now imagine thousands of images? The space consumption could be insane.

So you fix is either to, move all you images to a CDN like Amazon Cloudfront or Akamai or solve the problem in Sitecore.

By default the path for media caching is {Media Cache Folder)/{Site Name}/{Hash of media item}. The part I would like to focus on is the {Site Name}. This means that for every site, there is a different media cache. This makes sense since each site could have its own encoding or image processing logic. But in our case, our 600 sites are sharing images and therefor the image logic is the same.

If we decompile the class Sitecore.Resources.Media.MediaCacheRecord we will find the GetRootFolder() function.

    /// <summary>Gets the root folder of the cache data.</summary>
    /// <returns>The get root folder.</returns>
    private string GetRootFolder()
    {
      SiteContext site = Context.Site;
      if (site != null)
        return site.MediaCachePath;
      return FileUtil.MakePath(Settings.Media.CacheFolder, 
        this.Media.MediaData.MediaItem.Database.Name);
    }

This function is in charge of determining the media path. If the request is coming from a defined site, then the MediaCachePath is returned from the site's site config. By default this MediaCachePath is defined as {Media Cache Folder)/{Site Name}. BUT if you set the MediaCachePath in your site config, it will return that.

<site 
name="site1" 
patch:before="site[@name='website']" 
enableTracking="true" hostName="site1.parent.com|*site1site.com" targetHostName="site1.parent.com" 
database="web" 
virtualFolder="/" 
physicalFolder="/" 
rootPath="/sitecore/content/sites/site1/" 
startItem="/home" 
domain="extranet" 
allowDebug="true" 
cacheHtml="true" 
htmlCacheSize="50MB" 
registryCacheSize="0" 
viewStateCacheSize="0" 
xslCacheSize="25MB" 
filteredItemsCacheSize="10MZB" 
enablePreview="true" 
enableWebEdit="true" 
enableDebugger="true" 
disableClientData="false" 
cacheRenderingParameters="true" 
renderingParametersCacheSize="10MB" 
enableItemLanguageFallback="false" 
mediaCachePath="/App_Data/MediaCache/ParentSite"
/>

Now as many sites as you need can use the same cache folder and not have duplicate images consume all your disk space.