Skip to content

Instantly share code, notes, and snippets.

@piotrbach
Last active January 29, 2021 10:39
Show Gist options
  • Save piotrbach/de6553bd768a2931f91cba5368c08555 to your computer and use it in GitHub Desktop.
Save piotrbach/de6553bd768a2931f91cba5368c08555 to your computer and use it in GitHub Desktop.
An image service for retrieving images from Azure for ImageProcessor. Read more on https://piotrbach.com/configuring-umbraco-media-on-azure-private-blob-storage
/// <summary>
/// An image service for retrieving images from Azure.
/// </summary>
public class AzureImageService : IImageService
{
private CloudBlobContainer _blobContainer;
private CloudStorageAccount _storageAccount;
private Dictionary<string, string> _settings = new Dictionary<string, string>();
/// <summary>
/// Gets or sets the prefix for the given implementation.
/// <remarks>
/// This value is used as a prefix for any image requests that should use this service.
/// </remarks>
/// </summary>
public string Prefix { get; set; } = string.Empty;
/// <summary>
/// Gets a value indicating whether the image service requests files from
/// the locally based file system.
/// </summary>
public bool IsFileLocalService => false;
/// <summary>
/// Gets or sets any additional settings required by the service.
/// </summary>
public Dictionary<string, string> Settings
{
get => this._settings;
set
{
this._settings = value;
this.InitService();
}
}
/// <summary>
/// Gets or sets the white list of <see cref="Uri" />.
/// </summary>
public Uri[] WhiteList { get; set; }
/// <summary>
/// Gets the image using the given identifier.
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<byte[]> GetImage(object id)
{
if (await _blobContainer.ExistsAsync())
{
//expecting id as "3gikqq22/example-image.png"
string sId = PrepareBlobName(id);
CloudBlockBlob blob = _blobContainer.GetBlockBlobReference(sId);
if (await blob.ExistsAsync())
{
using (MemoryStream memoryStream = MemoryStreamPool.Shared.GetStream())
{
await blob.DownloadToStreamAsync(memoryStream).ConfigureAwait(false);
return memoryStream.ToArray();
}
}
}
return null;
}
/// <summary>
/// Removes container prefix from blob path
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
private string PrepareBlobName(object id)
{
string sId = id.ToString();
if (sId.StartsWith($"/{this.Settings["Container"]}/"))
{
return sId.Substring(this.Settings["Container"].Length + 2);
}
return sId;
}
/// <summary>
/// Gets a value indicating whether the current request passes sanitizing rules.
/// </summary>
/// <param name="path">The image path.</param>
/// <returns>
/// <c>True</c> if the request is valid; otherwise, <c>False</c>.
/// </returns>
public bool IsValidRequest(string path) => ImageHelpers.IsValidImageExtension(path);
/// <summary>
/// Initialise the service.
/// </summary>
private void InitService()
{
// Retrieve storage accounts from connection string.
_storageAccount = CloudStorageAccount.Parse(this.Settings["StorageAccount"]);
// Create the blob client.
CloudBlobClient blobClient = _storageAccount.CreateCloudBlobClient();
string container = this.Settings.ContainsKey("Container")
? this.Settings["Container"]
: string.Empty;
BlobContainerPublicAccessType accessType = this.Settings.ContainsKey("AccessType")
? (BlobContainerPublicAccessType)Enum.Parse(typeof(BlobContainerPublicAccessType), this.Settings["AccessType"])
: BlobContainerPublicAccessType.Blob;
this._blobContainer = CreateContainer(blobClient, container, accessType);
}
/// <summary>
/// Returns the cache container, creating a new one if none exists.
/// </summary>
/// <param name="cloudBlobClient"><see cref="CloudBlobClient"/> where the container is stored.</param>
/// <param name="containerName">The name of the container.</param>
/// <param name="accessType"><see cref="BlobContainerPublicAccessType"/> indicating the access permissions.</param>
/// <returns>The <see cref="CloudBlobContainer"/></returns>
private static CloudBlobContainer CreateContainer(CloudBlobClient cloudBlobClient, string containerName, BlobContainerPublicAccessType accessType)
{
CloudBlobContainer container = cloudBlobClient.GetContainerReference(containerName);
if (!container.Exists())
{
container.Create();
container.SetPermissions(new BlobContainerPermissions { PublicAccess = accessType });
}
return container;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment