API reference for blob storage

Abstract

Use this reference to customize your solution to meet your blob storage requirements.

The Sitecore Azure Blob Storage module consists of the following assembly:

  • Sitecore.Framework.Data.Blobs - provides the AzureStorageBlobProvider class, which allows APIs to work with blob storage.

Sitecore exposes a BlobStorage API to include the underlying blob providers (for example, AzureStorageBlobProvider), and provides convenient APIs to work with blob storage. By default, the BlobStorage API consists of the following assemblies:

  • Sitecore.Framework.Data.Blobs.Abstractions - provides abstractions to implement blob providers for the Sitecore Blob Storage module.

  • Sitecore.Framework.Data.Blobs - provides convenient APIs so you can work with blob storage without having to know about the blob providers configured in Sitecore.

The databases in Sitecore can use one or more storage for blob storage. In Sitecore, the Database.BlobStorage property includes a list of blob providers that work with the Sitecore databases. The property also lists APIs that you can use to work as extension methods with blob storage, without having to know about the blob providers configured in Sitecore.

Use the following code to access BlobStorage in Sitecore:

BlobStorage blobStorage = Database.BlobStorage;

The following class name examples demonstrate how to use the Sitecore APIs from BlobStorage extensions:

Method

BlobExists

Description

Use this API with the Blob ID to check whether a a blob exists in a Blob Storage account.

Example

try
{
    var blobId = blobStorage.CreateBlobIdentifier(new Guid("B4D19D07-B3EB-4F7D-98EC-8BCB41CCC58E"));
    var isBlobExists = blobStorage.BlobExists(blobId);
}
catch (BlobProviderException ex)
{
    // Handle exception
}

Method

GetBlob

Description

Use this API with the Blob ID to get a specific blob from Blob Storage.

Example

try
            {
                var blobId = blobStorage.CreateBlobIdentifier(new Guid("B4D19D07-B3EB-4F7D-98EC-8BCB41CCC58E"));
                var blobStream = blobStorage.GetBlob(blobId);
            }
            catch (BlobProviderException ex)
            {
                // Handle exception
            }

Method

RemoveBlob

Description

Use this API with the Blob ID to remove the blob from Blob Storage.

Example

try
            {
                var blobId = blobStorage.CreateBlobIdentifier(new Guid("B4D19D07-B3EB-4F7D-98EC-8BCB41CCC58E"));
                blobStorage.RemoveBlob(blobId);
            }
            catch (BlobProviderException ex)
            {
                // Handle exception
            }

Method

SetBlob

Description

Use this API with the Blob ID to save the blob in Blob Storage.

Example

try
            {
                var blobId = blobStorage.CreateBlobIdentifier();
                using (var blobStream = new MemoryStream(Encoding.UTF8.GetBytes("SampleStream")))
                {
                    blobStorage.SetBlob(blobStream, blobId);
                }
            }
            catch (BlobProviderException ex)
            {
                // Handle exception
            }

Sitecore's blob storage garbage collection feature helps you delete orphaned blobs from Sitecore. Initiate the deletion by using the following method: Sitecore.Data.DefaultDatabase.BlobStorage.CleanupOrphanBlobs.

For example:

var database = Sitecore.Configuration.Factory.GetDatabase("master");
database.BlobStorage.CleanupOrphanBlobs();

There are a few different ways you can access the blob provider directly, if necessary:

  • Example 1:

    IBlobProviderAsync blobProvider = blobStorage.GetBlobProvider<AzureStorageBlobProvider>();
  • Example 2:

    IBlobProviderAsync blobProvider = blobStorage.GetDefaultBlobProvider<IBlobProviderAsync>();
  • Example 3:

    BlobIdentifier blobId = new BlobIdentifier("B4D19D07-B3EB-4F7D-98EC-8BCB41CCC58E");
    IBlobProviderAsync blobProvider = blobStorage.GetBlobProvider<IBlobProviderAsync>(blobId);
    

This following class name examples demonstrate how to use the Sitecore APIs from BlobProvider methods:

Method

BlobExists

Description

Use this API with the Blob ID to check whether the blob exists in Blob Storage.

Example

try
            {
                var blobId = blobProvider.CreateBlobIdentifier(new Guid("B4D19D07-B3EB-4F7D-98EC-8BCB41CCC58E"));
                var isBlobExists = blobProvider.BlobExists(blobId);
            }
            catch (BlobProviderException ex)
            {
                // Handle exception
            }

Method

GetBlob

Description

Use this API with the Blob ID to get a specific blob from Blob Storage.

Example

try
            {
                var blobId = blobProvider.CreateBlobIdentifier(new Guid("B4D19D07-B3EB-4F7D-98EC-8BCB41CCC58E"));
                var blobStream = blobProvider.GetBlob(blobId);
            }
            catch (BlobProviderException ex)
            {
                // Handle exception
            }

Method

RemoveBlob

Description

Use this API with the Blob ID to remove a blob from Blob Storage.

Example

try
            {
               blobProvider.RemoveBlob(blobId);
            }
           catch (BlobProviderException ex)
            {
                // Handle exception
            }

Method

SetBlob

Description

Use this API with the Blob ID to save a blob in Blob Storage.

Example

try
            {
                var blobId = blobProvider.CreateBlobIdentifier();
                using (var blobStream = new MemoryStream(Encoding.UTF8.GetBytes("SampleStream")))
                {
                    blobProvider.SetBlob(blobStream, blobId);
                }
            }
            catch (BlobProviderException ex)
            {
                // Handle exception
            }

You can extend blob provider methods, for example, if you want to extend the GetBlob API:

using Sitecore.Framework.Data.Blobs.Abstractions;
using Sitecore.Framework.Data.Blobs.Azure;
using System.IO;

namespace Documentation
{
    public class ExtendGetBlob : AzureStorageBlobProvider
    {
        public ExtendGetBlob(string connectionStringName, IPagedListProvider usedBlobIdsPagedListProvider) : 
            base(connectionStringName, usedBlobIdsPagedListProvider)
        {
        }

        public override Stream GetBlob(BlobIdentifier identifier)
        {
            var blobStream = base.GetBlob(identifier);

            // Code to extend the GetBlob default behavior

            return blobStream;
        }
    }
}

You can create your own blob providers by using the Sitecore.Framework.Data.Blobs.Abstractions APIs, for example, if you want to create an InMemoryBlobProvider API:

using Sitecore.Framework.Conditions;
using Sitecore.Framework.Data.Blobs.Abstractions;
using System;
using System.Collections.Generic;
using System.IO;

namespace Documentation
{
    public class InMemoryBlobProvider : IBlobProvider
    {
        private readonly string _scheme = "memoryblob";
        private IDictionary<Uri, byte[]> blobs = new Dictionary<Uri, byte[]>();

        private void ValidateIdentifier(BlobIdentifier identifier)
        {
            if (!CanHandle(identifier))
                throw new InvalidOperationException(
                    $"The identifier '{identifier}' is not in acceptable format by this provider");
        }

        private byte[] GetBytes(Stream input)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                input.CopyTo(ms);
                return ms.ToArray();
            }
        }

        public bool BlobExists(BlobIdentifier identifier)
        {
            Condition.Requires(identifier, nameof(identifier)).IsNotNull();

            if (string.IsNullOrEmpty(identifier.ToString()))
            {
                return false;
            }

            ValidateIdentifier(identifier);

            try
            {
                return blobs.ContainsKey(identifier.ToUri());
            }
            catch (Exception ex)
            {
                throw new BlobProviderException(ex.Message, ex.InnerException);
            }
        }

        public bool CanHandle(BlobIdentifier identifier)
        {
            return (identifier != null) &&
               Uri.TryCreate(identifier.ToString(), UriKind.Absolute, out Uri result) &&
               result.Scheme != null &&
               result.Scheme.Equals(_scheme, StringComparison.InvariantCultureIgnoreCase);
        }

        public BlobIdentifier CreateBlobIdentifier()
        {
            return new BlobIdentifier($"{_scheme}://{Guid.NewGuid()}");
        }

        public BlobIdentifier CreateBlobIdentifier(Guid guid)
        {
            Condition.Requires(guid, nameof(guid)).IsNotEqualTo(Guid.Empty);

            return new BlobIdentifier($"{_scheme}://{guid}");
        }

        public Guid ToGuid(BlobIdentifier identifier)
        {
            Condition.Requires(identifier, nameof(identifier)).IsNotNull();
            ValidateIdentifier(identifier);

            return new Guid(new Uri(identifier.ToString()).Host);
        }

        public Stream GetBlob(BlobIdentifier identifier)
        {
            Condition.Requires(identifier, nameof(identifier)).IsNotNull();

            if (string.IsNullOrEmpty(identifier.ToString()))
            {
                return null;
            }

            ValidateIdentifier(identifier);

            try
            {
                if (blobs.ContainsKey(identifier.ToUri()))
                {
                    return new MemoryStream(blobs[identifier.ToUri()]);
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                throw new BlobProviderException(ex.Message, ex.InnerException);
            }
        }

        public void RemoveBlob(BlobIdentifier identifier)
        {
            Condition.Requires(identifier, nameof(identifier)).IsNotNull();

            ValidateIdentifier(identifier);

            if (blobs.ContainsKey(identifier.ToUri()))
            {
                blobs.Remove(identifier.ToUri());
            }
        }

        public void SetBlob(Stream stream, BlobIdentifier identifier)
        {
            Condition.Requires(stream, nameof(stream)).IsNotNull();
            Condition.Requires(identifier, nameof(identifier)).IsNotNull();

            ValidateIdentifier(identifier);

            blobs[identifier.ToUri()] = GetBytes(stream);
        }
        
    }

    public static class BlobIdentifierExtensions
    {
        public static bool IsUri(this BlobIdentifier identifier)
        {
            if (identifier != null && !string.IsNullOrWhiteSpace(identifier.ToString()))
            {
                string blobId = identifier.ToString();
                if (Uri.IsWellFormedUriString(blobId, UriKind.Absolute))
                {
                    return true;
                }
            }
            return false;
        }

        public static Uri ToUri(this BlobIdentifier identifier)
        {
            Condition.Requires(identifier, nameof(identifier)).IsNotNull();

            if (!identifier.IsUri())
            {
                throw new ArgumentException($"Provided identifier {identifier.ToString()} is not a valid Uri.");
            }

            return new Uri(identifier.ToString());
        }
    }
}