Can’t Publish Media Items to Sitecore Publishing Target
Upon adding additional publishing targets to an environment, the Sitecore CMS had no issues publishing items… except for Media items. In fact, it was throwing the following error since Media items are stored via Blob Storage which is different than normal Sitecore items due to the nature of media files:
6724 15:16:33 ERROR An error during Publish Pipeline Process Queue execution.
Exception: System.InvalidOperationException
Message: BlobStorage
Source: Sitecore.Kernel
at Sitecore.Data.Fields.Field.GetBlobStorage()
at Sitecore.Data.Fields.Field.get_HasBlobStream()
at Sitecore.Publishing.PublishHelper.CopyBlobField(Field sourceField, Item targetVersion)
at Sitecore.Publishing.PublishHelper.CopyBlobFields(Item sourceVersion, Item targetVersion)
at Sitecore.Publishing.PublishHelper.TransformToTargetVersion(Item sourceVersion)
at Sitecore.Publishing.PublishHelper.CopyToTarget(Item sourceVersion, Item originalItem)
at Sitecore.Publishing.PublishHelper.PublishVersionToTarget(Item sourceVersion, Item targetItem, Boolean targetCreated)
at Sitecore.Publishing.PublishHelper.PublishVersion(Item sourceVersion)
at Sitecore.Publishing.Pipelines.PublishItem.PerformAction.Process(PublishItemContext context)
at (Object , Object )
at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
at Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain)
at Sitecore.Publishing.Pipelines.PublishItem.PublishItemPipeline.Run(PublishItemContext context)
at Sitecore.Publishing.Pipelines.Publish.ProcessQueue.ProcessPublishingCandidate(PublishingCandidate entry, PublishContext context, List`1& referrers, List`1& children)
at Sitecore.Publishing.Pipelines.Publish.ProcessQueue.ProcessPublishingCandidate(PublishingCandidate entry, PublishContext context)
at Sitecore.Publishing.Pipelines.Publish.ProcessQueue.ProcessEntries(IEnumerable`1 entries, PublishContext context)
at Sitecore.Publishing.Pipelines.Publish.ProcessQueue.ProcessPublishingCandidate(PublishingCandidate entry, PublishContext context)
at Sitecore.Publishing.Pipelines.Publish.ProcessQueue.ProcessEntries(IEnumerable`1 entries, PublishContext context)
at Sitecore.Publishing.Pipelines.Publish.ProcessQueue.ProcessEntries(PublishContext context)
at Sitecore.Publishing.Pipelines.Publish.ProcessQueue.Process(PublishContext context)
In double checking that the Publishing Target was configured per Sitecore documentation (Create a publishing target | Sitecore Documentation), I noticed that there were no references to BlobStorage per the recommended configuration.
However, the default Internet publishing target was able to publish Media items. Opening the Sitecore.config file and reviewing the default configuration for the web database, it had the BlobStorage references right after </cacheSizes> and before the end tag of </database> (not </databases> as we want to ensure that the BlobStorage reference is nested within the database definition/id)
<BlobStorage hint="raw:AddBlobStorage">
<providers default="classic">
<provider name="classic" type="Sitecore.Data.Blobs.ClassicSqlBlobProvider, Sitecore.Kernel">
<param desc="databaseName">$(id)</param>
</provider>
</providers>
</BlobStorage>
My final patch file for adding the Preview Publishing Target with the BlobStorage ended up as follows. With this in place the publishing of Media items worked. So remember, beyond ensuring that the .dat files are properly created for your new publishing target, you should also cross reference the default publishing target if you come across publishing errors.
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<eventing defaultProvider="sitecore">
<eventQueueProvider>
<eventQueue name="preview" patch:after="eventQueue[@name='web']" type="Sitecore.Data.Eventing.$(database)EventQueue, Sitecore.Kernel">
<param ref="dataApis/dataApi[@name='$(database)']" param1="$(name)" />
<param hint="" ref="PropertyStoreProvider/store[@name='$(name)']" />
</eventQueue>
</eventQueueProvider>
</eventing>
<PropertyStoreProvider>
<store name="preview" patch:after="store[@name='web']" prefix="preview" getValueWithoutPrefix="true" singleInstance="true" type="Sitecore.Data.Properties.$(database)PropertyStore, Sitecore.Kernel">
<param ref="dataApis/dataApi[@name='$(database)']" param1="$(name)" />
<param resolve="true" type="Sitecore.Abstractions.BaseEventManager, Sitecore.Kernel" />
<param resolve="true" type="Sitecore.Abstractions.BaseCacheManager, Sitecore.Kernel" />
</store>
</PropertyStoreProvider>
<databases>
<!-- web_secondary -->
<database id="preview" patch:after="database[@id='web']" singleInstance="true" type="Sitecore.Data.DefaultDatabase, Sitecore.Kernel">
<param desc="name">$(id)</param>
<icon>Images/database_web.png</icon>
<securityEnabled>true</securityEnabled>
<dataProviders hint="list:AddDataProvider">
<dataProvider type="Sitecore.Data.DataProviders.CompositeDataProvider, Sitecore.Kernel">
<param desc="readOnlyDataProviders" hint="list">
<protobufItems type="Sitecore.Data.DataProviders.ReadOnly.Protobuf.ProtobufDataProvider, Sitecore.Kernel">
<filePaths hint="list">
<filePath>$(dataFolder)/items/$(id)</filePath>
<modulesFilePath>/sitecore modules/items/$(id)</modulesFilePath>
</filePaths>
</protobufItems>
</param>
<param desc="headProvider">
<dataProvider ref="dataProviders/main" param1="$(id)">
<disableGroup>publishing</disableGroup>
<prefetch hint="raw:AddPrefetch">
<sc.include file="/App_Config/Prefetch/Common.config" />
<sc.include file="/App_Config/Prefetch/Webdb.config" />
</prefetch>
</dataProvider>
</param>
</dataProvider>
</dataProviders>
<PropertyStore ref="PropertyStoreProvider/store[@name='$(id)']" />
<remoteEvents.EventQueue>
<obj ref="eventing/eventQueueProvider/eventQueue[@name='$(id)']" />
</remoteEvents.EventQueue>
<archives hint="raw:AddArchive">
<archive name="archive" />
<archive name="recyclebin" />
</archives>
<cacheSizes hint="setting">
<data>100MB</data>
<items>50MB</items>
<paths>2500KB</paths>
<itempaths>50MB</itempaths>
<standardValues>2500KB</standardValues>
</cacheSizes>
<BlobStorage hint="raw:AddBlobStorage">
<providers default="classic">
<provider name="classic" type="Sitecore.Data.Blobs.ClassicSqlBlobProvider, Sitecore.Kernel">
<param desc="databaseName">$(id)</param>
</provider>
</providers>
</BlobStorage>
</database>
</databases>
</sitecore>
</configuration>