Files
social-media/src/Infrastructure/AzureBlob/AzureBlobStorageService.cs
2024-07-10 01:51:08 -04:00

137 lines
5.5 KiB
C#

using Azure;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Hutopy.Application.Common.Interfaces;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace Hutopy.Infrastructure.AzureBlob;
public class AzureBlobStorageService : IAzureBlobStorageService
{
private readonly BlobServiceClient _blobServiceClient;
private readonly ILogger<AzureBlobStorageService> _logger;
private readonly long _maxUploadSize = 10 * 1024 * 1024; // 10 MB in bytes
public AzureBlobStorageService(IConfiguration configuration, ILogger<AzureBlobStorageService> logger)
{
_logger = logger;
var connectionString = configuration["Azure-Blob-Connection-String"] ?? "";
_blobServiceClient = new BlobServiceClient(connectionString);
}
/// <summary>
/// Upload a file to microsoft azure blob storage.
/// </summary>
/// <param name="blobName">The blob name (path within the container, include the file name).</param>
/// <param name="containerName">The name of the container where the file is stored.</param>
/// <param name="fileStream">The stream.</param>
/// <param name="contentType">The content type.</param>
/// <returns></returns>
public async Task<string> UploadFileAsync(string containerName, string blobName, Stream fileStream, string contentType)
{
// Read the file stream into a memory stream to determine the length
// WATCH FOR MEMORY USAGE USING THE MEMORY STREAM.
var memoryStream = new MemoryStream();
await fileStream.CopyToAsync(memoryStream);
memoryStream.Position = 0;
// Check if the file size exceeds the maximum upload size
if (memoryStream.Length > _maxUploadSize)
{
_logger.LogInformation($"Blob storage: File size exceeds the maximum allowed size of {_maxUploadSize} bytes.");
throw new InvalidOperationException($"Blob storage: File size exceeds the maximum allowed size of {_maxUploadSize} bytes.");
}
// Validate content type
if (!ContentTypes.IsAllowed(contentType, memoryStream))
{
_logger.LogInformation($"Blob storage: Unsupported file type {contentType}. Only PNG and JPEG are allowed.");
throw new InvalidOperationException("Unsupported file type. Only PNG and JPEG are allowed.");
}
try
{
// Get a reference to a container
var containerClient = _blobServiceClient.GetBlobContainerClient(containerName);
// Create the container if it does not exist
await containerClient.CreateIfNotExistsAsync();
// Get a reference to a blob
var blobClient = containerClient.GetBlobClient(blobName);
// Define the BlobHttpHeaders to include the content type
var blobHttpHeaders = new BlobHttpHeaders
{
ContentType = contentType
};
// Upload the file
var response = await blobClient.UploadAsync(memoryStream, new BlobUploadOptions
{
HttpHeaders = blobHttpHeaders
});
var fileUri = blobClient.Uri.ToString();
_logger.LogInformation(
$"Blob storage: Status [ {response.GetRawResponse().Status.ToString()} ] " +
$"Uploaded [ {blobName} ] to the container [ {containerName} ] " +
$"with contentType [ {contentType} ] " +
$"with a length of [ {memoryStream.Length} bytes ]" +
$"with the uri [ {fileUri} ]"
);
// Return the URI of the uploaded blob
return fileUri;
}
catch (RequestFailedException ex)
{
_logger.LogError($"Blob storage: Azure Storage request failed: {ex.Message}");
throw new Exception("Error uploading file to Azure Blob Storage", ex);
}
catch (Exception ex)
{
_logger.LogError($"Blob storage: An error occurred: {ex.Message}");
throw;
}
}
/// <summary>
/// Download a file to microsoft azure blob storage.
/// </summary>
/// <param name="blobName">The blob name (path within the container).</param>
/// <param name="containerName">The name of the container where the file is stored. (users)</param>
/// <returns></returns>
public async Task<MemoryStream> DownloadFileAsync(string containerName, string blobName)
{
try
{
// Get a reference to a container
var containerClient = _blobServiceClient.GetBlobContainerClient(containerName);
// Get a reference to a blob
var blobClient = containerClient.GetBlobClient(blobName);
// Download the blob to a stream
BlobDownloadInfo download = await blobClient.DownloadAsync();
MemoryStream memoryStream = new();
await download.Content.CopyToAsync(memoryStream);
memoryStream.Position = 0; // Ensure the stream is at the beginning
return memoryStream;
}
catch (RequestFailedException ex)
{
_logger.LogError($"Azure Storage request failed: {ex.Message}");
throw new Exception("Error downloading file from Azure Blob Storage", ex);
}
catch (Exception ex)
{
_logger.LogError($"An error occurred: {ex.Message}");
throw new ApplicationException("Error downloading file from Azure Blob Storage.", ex);
}
}
}