Last active
January 29, 2021 10:39
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <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