I’ve been spending a bit of time helping out a client who’s working through an upgrade project recently, and the work to move from v9.1 to v9.3 raised an interesting issue I wasn’t aware of. So in the spirit of making life easier for others, here’s what happened:
After many years, I’ve finally decided to start moving off WordPress and onto a blog I host myself. This post is now available at “https://blog.jermdavis.dev/posts/2020/watch-your-blobs-when-upgrading-to-v9-3“. Eventually this version will be retired so please update links on any sites you control, to avoid 404s in the future.
The project in question had a distributed instance of Sitecore. Because of the distance between master and the web database, Publishing Service was in use. Plus there were multiple web databases set up as Publishing Targets.
After some initial work on the upgrade, Sitecore would start up and Content Editor ran. However when you looked at the public site, all the images were broken. They didn’t load in the pages, and if you requested one directly you’d see something like:
Under the surface, the stack trace in the logs was:
1192 20:34:01 ERROR Could not run the 'getMediaStream' pipeline for '/sitecore/media library/Default Website/cover'. Original media data will be used. Exception: System.InvalidOperationException Message: BlobStorage Source: Sitecore.Kernel at Sitecore.Data.Fields.Field.GetBlobStorage() at Sitecore.Data.Fields.Field.GetBlobStream() at Sitecore.Resources.Media.MediaData.GetBlobStream() at Sitecore.Resources.Media.GetMediaStreamPipelineArgs.get_OutputStream() at Sitecore.Resources.Media.ResizeProcessor.Process(GetMediaStreamPipelineArgs args) at (Object , Object ) at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args) at Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain, Boolean failIfNotExists) at Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain) at Sitecore.Resources.Media.Media.GetStreamFromPipeline(MediaOptions options, Boolean& canBeCached)
And if you pointed Content Editor at the Publishing Target that the public site was using, it worked fine until you selected the Media item for one of the images. And then you’d see much the same error in the Content Editor:
After a certain amount of googling and frustration, I came across a blog post relating to a similar error, which gave me the hint I needed to get to the bottom of this: It describes the need for a
<BlobStorage/> element in config. That post then lead on to Sitecore’s documentation of v9.3’s new Azure Blob Storage module.
So it seems that v9.3 has added a new extension point for customising how the binary data for Media Items is stored. Historically that was always in the
Blobs table inside your content databases. But now it’s configurable – so each database definition in your config needs a
The documentation largely describes setting this up for Azure Blob Storage, but it also covers the settings required for the old SQL database approach (which is also what the blog post above mentioned).
So the installation of Sitecore v9.3 for this project was working ok, except for the fact that the extra publishing targets were created with config patches written for Sitecore v9.1. So they did not have this extra config.
Based on the blog post above and the Sitecore docs, the solution is to add a blob storage provider to each of the publishing targets:
<database id="custom-publishing-target"> <BlobStorage> <providers default="classic"> <provider name="classic" type="Sitecore.Data.Blobs.ClassicSqlBlobProvider, Sitecore.Kernel"> <param desc="databaseName">$(id)</param> </provider> </providers> </BlobStorage> </database>
And once that’s in place, Sitecore knows where to find the blobs for these databases, getting rid of the error.
So that covered Sitecore – but a load of googling didn’t bring up anything about how this might affect Publishing Service. I ended up discussing this with Sitecore Support, who filled in the last bits of the puzzle for me. Given I’d had to add specific config for this to Sitecore I was concerned that there might be some sort of config change required to ensure Publishing Service knew where the blobs were, so it could know what to do with them.
But according to Support, Publishing Service doesn’t actually care what your blob provider is. If the blobs are in SQL Server tables in your content database, then they’ll get published because that’s how blobs used to be dealt with. But if the blobs are in Azure, then there are no records in the content database blob table – so Publishing Service will have nothing to do there – and the images are already sat in Azure Blob Storage, ready to be served…
So, as long as you remember to add the default SQL blob provider to all your custom Publishing Targets when you’re upgrading, everything will work.
And big thanks to Colin Cooper, for the blog post that unlocked this for me.