137 lines
5.5 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|