From 41033ca58020d9729294d37ae0850cfd20da24ff Mon Sep 17 00:00:00 2001 From: sdcb Date: Fri, 6 Dec 2024 13:16:27 +0800 Subject: [PATCH] complete azure blob storage --- src/BE/Chats.BE.csproj | 3 ++- .../FileServices/FileServiceFactory.cs | 2 +- .../FileServices/FileUploadRequest.cs | 2 +- .../AliyunOSS/AliyunOSSFileService.cs | 2 +- .../Implementations/AwsS3/AwsS3FileService.cs | 2 +- .../AzureBlobStorageConfig.cs | 12 ++++++++++ .../AzureBlobStorageFileService.cs | 24 ++++++++++++++----- 7 files changed, 36 insertions(+), 11 deletions(-) create mode 100644 src/BE/Services/FileServices/Implementations/AzureBlobStorage/AzureBlobStorageConfig.cs diff --git a/src/BE/Chats.BE.csproj b/src/BE/Chats.BE.csproj index ea27d80b..f9771798 100644 --- a/src/BE/Chats.BE.csproj +++ b/src/BE/Chats.BE.csproj @@ -11,7 +11,8 @@ - + + all diff --git a/src/BE/Services/FileServices/FileServiceFactory.cs b/src/BE/Services/FileServices/FileServiceFactory.cs index e35474a2..a710f20d 100644 --- a/src/BE/Services/FileServices/FileServiceFactory.cs +++ b/src/BE/Services/FileServices/FileServiceFactory.cs @@ -34,7 +34,7 @@ private IFileService CreateNoCache(DBFileServiceType fileServiceType, string con DBFileServiceType.Minio => new MinioFileService(JsonSerializer.Deserialize(config)!), DBFileServiceType.AwsS3 => new AwsS3FileService(JsonSerializer.Deserialize(config)!), DBFileServiceType.AliyunOSS => new AliyunOSSFileService(JsonSerializer.Deserialize(config)!), - DBFileServiceType.AzureBlobStorage => new AzureBlobStorageFileService(config), + DBFileServiceType.AzureBlobStorage => new AzureBlobStorageFileService(JsonSerializer.Deserialize(config)!), _ => throw new ArgumentException($"Unsupported file service type: {fileServiceType}") }; } diff --git a/src/BE/Services/FileServices/FileUploadRequest.cs b/src/BE/Services/FileServices/FileUploadRequest.cs index 20e23a5b..59b8ff62 100644 --- a/src/BE/Services/FileServices/FileUploadRequest.cs +++ b/src/BE/Services/FileServices/FileUploadRequest.cs @@ -34,7 +34,7 @@ public record CreateDownloadUrlRequest public required int FileId { get; init; } public required string StorageKey { get; init; } public TimeSpan ValidPeriod { get; init; } = TimeSpan.FromHours(2); - public DateTime ValidEnd => DateTime.UtcNow + ValidPeriod; + public DateTimeOffset ValidEnd => DateTimeOffset.UtcNow + ValidPeriod; public static CreateDownloadUrlRequest FromFile(DB.File file) { diff --git a/src/BE/Services/FileServices/Implementations/AliyunOSS/AliyunOSSFileService.cs b/src/BE/Services/FileServices/Implementations/AliyunOSS/AliyunOSSFileService.cs index 81e090cd..6cc0e5f1 100644 --- a/src/BE/Services/FileServices/Implementations/AliyunOSS/AliyunOSSFileService.cs +++ b/src/BE/Services/FileServices/Implementations/AliyunOSS/AliyunOSSFileService.cs @@ -8,7 +8,7 @@ public class AliyunOSSFileService(AliyunOssConfig config) : IFileService public Uri CreateDownloadUrl(CreateDownloadUrlRequest req) { - return _oss.GeneratePresignedUri(config.Bucket, req.StorageKey, req.ValidEnd, SignHttpMethod.Get); + return _oss.GeneratePresignedUri(config.Bucket, req.StorageKey, req.ValidEnd.UtcDateTime, SignHttpMethod.Get); } public Task Download(string storageKey, CancellationToken cancellationToken) diff --git a/src/BE/Services/FileServices/Implementations/AwsS3/AwsS3FileService.cs b/src/BE/Services/FileServices/Implementations/AwsS3/AwsS3FileService.cs index ab700c18..ed28a64e 100644 --- a/src/BE/Services/FileServices/Implementations/AwsS3/AwsS3FileService.cs +++ b/src/BE/Services/FileServices/Implementations/AwsS3/AwsS3FileService.cs @@ -38,7 +38,7 @@ public Uri CreateDownloadUrl(CreateDownloadUrlRequest req) { BucketName = _config.Bucket, Key = req.StorageKey, - Expires = req.ValidEnd, + Expires = req.ValidEnd.UtcDateTime, Verb = HttpVerb.GET }); return new Uri(url); diff --git a/src/BE/Services/FileServices/Implementations/AzureBlobStorage/AzureBlobStorageConfig.cs b/src/BE/Services/FileServices/Implementations/AzureBlobStorage/AzureBlobStorageConfig.cs new file mode 100644 index 00000000..d5cb7447 --- /dev/null +++ b/src/BE/Services/FileServices/Implementations/AzureBlobStorage/AzureBlobStorageConfig.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace Chats.BE.Services.FileServices.Implementations.AzureBlobStorage; + +public record AzureBlobStorageConfig +{ + [JsonPropertyName("connectionString")] + public required string ConnectionString { get; init; } + + [JsonPropertyName("containerName")] + public required string ContainerName { get; init; } +} diff --git a/src/BE/Services/FileServices/Implementations/AzureBlobStorage/AzureBlobStorageFileService.cs b/src/BE/Services/FileServices/Implementations/AzureBlobStorage/AzureBlobStorageFileService.cs index e3c567cd..43abb9ac 100644 --- a/src/BE/Services/FileServices/Implementations/AzureBlobStorage/AzureBlobStorageFileService.cs +++ b/src/BE/Services/FileServices/Implementations/AzureBlobStorage/AzureBlobStorageFileService.cs @@ -1,21 +1,33 @@ - +using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Models; +using Azure.Storage.Sas; namespace Chats.BE.Services.FileServices.Implementations.AzureBlobStorage; -public class AzureBlobStorageFileService(string azureStorageConnectionString) : IFileService +public class AzureBlobStorageFileService(AzureBlobStorageConfig config) : IFileService { + private readonly BlobContainerClient _containerClient = new(config.ConnectionString, config.ContainerName); + public Uri CreateDownloadUrl(CreateDownloadUrlRequest req) { - throw new NotImplementedException(); + BlobClient blobClient = _containerClient.GetBlobClient(req.StorageKey); + return blobClient.GenerateSasUri(BlobSasPermissions.Read, req.ValidEnd); } public Task Download(string storageKey, CancellationToken cancellationToken) { - throw new NotImplementedException(); + BlobClient blobClient = _containerClient.GetBlobClient(storageKey); + return blobClient.OpenReadAsync(new BlobOpenReadOptions(allowModifications: false), cancellationToken); } - public Task Upload(FileUploadRequest request, CancellationToken cancellationToken) + public async Task Upload(FileUploadRequest request, CancellationToken cancellationToken) { - throw new NotImplementedException(); + SuggestedStorageInfo suggestedStorageInfo = SuggestedStorageInfo.FromFileName(request.FileName); + BlobClient blobClient = _containerClient.GetBlobClient(suggestedStorageInfo.StorageKey); + _ = await blobClient.UploadAsync(request.Stream, new BlobUploadOptions + { + HttpHeaders = new BlobHttpHeaders { ContentType = request.ContentType }, + }, cancellationToken); + return suggestedStorageInfo.StorageKey; } }