From 423c881fd628303f3d9dc897e20646e31a38350a Mon Sep 17 00:00:00 2001 From: colin Date: Mon, 28 Apr 2025 20:11:05 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat(oss):=20=E5=A2=9E=E5=8A=A0oss=E5=AD=98?= =?UTF-8?q?=E5=82=A8=E6=98=AF=E5=90=A6=E5=AD=98=E5=9C=A8=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Aliyun/AliyunOssContainer.cs | 13 ++++++ .../Abp/OssManagement/IOssContainer.cs | 6 +++ .../Abp/OssManagement/OssContainerBase.cs | 2 + .../FileSystem/FileSystemOssContainer.cs | 16 +++++++ .../Abp/OssManagement/OssObjectController.cs | 46 ++++++++++++++----- .../OssManagement/Minio/MinioOssContainer.cs | 14 ++++++ .../OssManagement/Nexus/NexusOssContainer.cs | 16 +++++++ .../Tencent/TencentOssContainer.cs | 13 ++++++ 8 files changed, 114 insertions(+), 12 deletions(-) diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/LINGYUN/Abp/OssManagement/Aliyun/AliyunOssContainer.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/LINGYUN/Abp/OssManagement/Aliyun/AliyunOssContainer.cs index 59293f610..b5805cae9 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/LINGYUN/Abp/OssManagement/Aliyun/AliyunOssContainer.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/LINGYUN/Abp/OssManagement/Aliyun/AliyunOssContainer.cs @@ -62,6 +62,19 @@ internal class AliyunOssContainer : OssContainerBase, IOssObjectExpireor }); } + public async override Task ObjectExistsAsync(GetOssObjectRequest request) + { + var ossClient = await CreateClientAsync(); + + var objectPath = GetBasePath(request.Path); + + var objectName = objectPath.IsNullOrWhiteSpace() + ? request.Object + : objectPath + request.Object; + + return ObjectExists(ossClient, request.Bucket, objectName); + } + public async override Task CreateObjectAsync(CreateOssObjectRequest request) { var ossClient = await CreateClientAsync(); diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/IOssContainer.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/IOssContainer.cs index 5f5169a1b..a88cc5524 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/IOssContainer.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/IOssContainer.cs @@ -60,6 +60,12 @@ public interface IOssContainer /// Task ExistsAsync(string name); /// + /// Oss对象是否存在 + /// + /// + /// + Task ObjectExistsAsync(GetOssObjectRequest request); + /// /// 获取容器列表 /// /// diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/OssContainerBase.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/OssContainerBase.cs index ecd8670b3..27903ff33 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/OssContainerBase.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/OssContainerBase.cs @@ -65,4 +65,6 @@ public abstract class OssContainerBase : IOssContainer { return true; } + + public abstract Task ObjectExistsAsync(GetOssObjectRequest request); } diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/FileSystemOssContainer.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/FileSystemOssContainer.cs index c27003be8..6f9d3e28f 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/FileSystemOssContainer.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/FileSystemOssContainer.cs @@ -122,6 +122,22 @@ internal class FileSystemOssContainer : OssContainerBase, IOssObjectExpireor return Task.CompletedTask; } + public override Task ObjectExistsAsync(GetOssObjectRequest request) + { + var objectPath = !request.Path.IsNullOrWhiteSpace() + ? request.Path.EnsureEndsWith('/') + : ""; + var objectName = objectPath.IsNullOrWhiteSpace() + ? request.Object + : objectPath + request.Object; + + var filePath = CalculateFilePath(request.Bucket, objectName); + + var objectExists = File.Exists(filePath) || Directory.Exists(filePath); + + return Task.FromResult(objectExists); + } + public async override Task CreateObjectAsync(CreateOssObjectRequest request) { var objectPath = !request.Path.IsNullOrWhiteSpace() diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/OssObjectController.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/OssObjectController.cs index 5e5d98a69..346be5846 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/OssObjectController.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/OssObjectController.cs @@ -1,6 +1,7 @@ using LINGYUN.Abp.OssManagement.Permissions; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using System; using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.AspNetCore.Mvc; @@ -26,43 +27,64 @@ public class OssObjectController : AbpControllerBase, IOssObjectAppService } [HttpPost] - public async virtual Task CreateAsync([FromForm] CreateOssObjectInput input) + [Authorize(AbpOssManagementPermissions.OssObject.Create)] + public virtual Task CreateAsync([FromForm] CreateOssObjectInput input) { - return await OssObjectAppService.CreateAsync(input); + return OssObjectAppService.CreateAsync(input); } [HttpPost] [Route("upload")] [DisableAuditing] [Authorize(AbpOssManagementPermissions.OssObject.Create)] - public async virtual Task UploadAsync([FromForm] UploadFileChunkInput input) + public virtual Task UploadAsync([FromForm] UploadFileChunkInput input) { - await FileUploader.UploadAsync(input); + return FileUploader.UploadAsync(input); } [HttpPost] [Route("bulk-delete")] - public async virtual Task BulkDeleteAsync(BulkDeleteOssObjectInput input) + [Authorize(AbpOssManagementPermissions.OssObject.Delete)] + public virtual Task BulkDeleteAsync(BulkDeleteOssObjectInput input) { - await OssObjectAppService.BulkDeleteAsync(input); + return OssObjectAppService.BulkDeleteAsync(input); } [HttpDelete] - public async virtual Task DeleteAsync(GetOssObjectInput input) + [Authorize(AbpOssManagementPermissions.OssObject.Delete)] + public virtual Task DeleteAsync(GetOssObjectInput input) { - await OssObjectAppService.DeleteAsync(input); + return OssObjectAppService.DeleteAsync(input); } [HttpGet] - public async virtual Task GetAsync(GetOssObjectInput input) + [Authorize(AbpOssManagementPermissions.OssObject.Default)] + public virtual Task GetAsync(GetOssObjectInput input) { - return await OssObjectAppService.GetAsync(input); + return OssObjectAppService.GetAsync(input); } [HttpGet] [Route("download")] - public async virtual Task GetContentAsync(GetOssObjectInput input) + [Authorize(AbpOssManagementPermissions.OssObject.Download)] + [Obsolete("请使用 GenerateUrlAsync 与 DownloadAsync的组合")] + public virtual Task GetContentAsync(GetOssObjectInput input) + { + return OssObjectAppService.GetContentAsync(input); + } + + [HttpGet] + [Route("generate-url")] + [Authorize(AbpOssManagementPermissions.OssObject.Download)] + public virtual Task GenerateUrlAsync(GetOssObjectInput input) + { + return OssObjectAppService.GenerateUrlAsync(input); + } + + [HttpGet] + [Route("download/{urlKey}")] + public virtual Task DownloadAsync(string urlKey) { - return await OssObjectAppService.GetContentAsync(input); + return OssObjectAppService.DownloadAsync(urlKey); } } diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Minio/LINGYUN/Abp/OssManagement/Minio/MinioOssContainer.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Minio/LINGYUN/Abp/OssManagement/Minio/MinioOssContainer.cs index 5b81355c7..f2378750f 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Minio/LINGYUN/Abp/OssManagement/Minio/MinioOssContainer.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Minio/LINGYUN/Abp/OssManagement/Minio/MinioOssContainer.cs @@ -95,6 +95,20 @@ public class MinioOssContainer : OssContainerBase, IOssObjectExpireor new Dictionary()); } + public async override Task ObjectExistsAsync(GetOssObjectRequest request) + { + var client = GetMinioClient(); + + var bucket = GetBucket(request.Bucket); + var prefixPath = GetPrefixPath(); + var objectPath = GetBlobPath(prefixPath, request.Path); + var objectName = objectPath.IsNullOrWhiteSpace() + ? request.Object + : objectPath + request.Object; + + return await ObjectExists(client, bucket, objectName); + } + public async override Task CreateObjectAsync(CreateOssObjectRequest request) { var client = GetMinioClient(); diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Nexus/LINGYUN/Abp/OssManagement/Nexus/NexusOssContainer.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Nexus/LINGYUN/Abp/OssManagement/Nexus/NexusOssContainer.cs index 85e06ec8f..197059da4 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Nexus/LINGYUN/Abp/OssManagement/Nexus/NexusOssContainer.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Nexus/LINGYUN/Abp/OssManagement/Nexus/NexusOssContainer.cs @@ -77,6 +77,22 @@ internal class NexusOssContainer : OssContainerBase, IOssObjectExpireor DateTime.Now); } + public async override Task ObjectExistsAsync(GetOssObjectRequest request) + { + var nexusConfiguration = GetNexusConfiguration(); + var blobPath = GetBasePath(request.Bucket, request.Path, request.Object); + + var searchBlobName = GetObjectName(request.Bucket, request.Path, request.Object); + var nexusSearchArgs = new NexusSearchArgs( + nexusConfiguration.Repository, + blobPath, + searchBlobName); + + var nexusAssetListResult = await NexusLookupService.ListAssetAsync(nexusSearchArgs); + + return nexusAssetListResult.Items.Count != 0; + } + public async override Task CreateObjectAsync(CreateOssObjectRequest request) { var nexusConfiguration = GetNexusConfiguration(); diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Tencent/LINGYUN/Abp/OssManagement/Tencent/TencentOssContainer.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Tencent/LINGYUN/Abp/OssManagement/Tencent/TencentOssContainer.cs index d39ddfcca..87153273f 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Tencent/LINGYUN/Abp/OssManagement/Tencent/TencentOssContainer.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Tencent/LINGYUN/Abp/OssManagement/Tencent/TencentOssContainer.cs @@ -71,6 +71,19 @@ internal class TencentOssContainer : OssContainerBase, IOssObjectExpireor }); } + public async override Task ObjectExistsAsync(GetOssObjectRequest request) + { + var ossClient = await CreateClientAsync(); + + var objectPath = GetBasePath(request.Path); + + var objectName = objectPath.IsNullOrWhiteSpace() + ? request.Object + : objectPath + request.Object; + + return ObjectExists(ossClient, request.Bucket, objectName); + } + public async override Task CreateObjectAsync(CreateOssObjectRequest request) { var ossClient = await CreateClientAsync(); From 558b3c38d51c888cf09928c9cca42c69204b4014 Mon Sep 17 00:00:00 2001 From: colin Date: Mon, 28 Apr 2025 20:13:10 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat(oss):=20=E5=88=86=E7=89=87=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=E6=96=87=E4=BB=B6=E5=90=88=E5=B9=B6=E5=89=8D=E6=A3=80?= =?UTF-8?q?=E6=9F=A5=E6=96=87=E4=BB=B6=E6=98=AF=E5=90=A6=E5=AD=98=E5=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Abp/OssManagement/GetOssObjectInput.cs | 1 + .../OssManagement/ValidationOssObjectInput.cs | 28 +++++++++++++++++++ .../Abp/OssManagement/FileUploadMerger.cs | 21 +++++++++++++- .../LINGYUN/Abp/OssManagement/FileUploader.cs | 14 ++++++---- 4 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/ValidationOssObjectInput.cs diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/GetOssObjectInput.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/GetOssObjectInput.cs index ff3ccbafa..f9c92ebbf 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/GetOssObjectInput.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/GetOssObjectInput.cs @@ -11,5 +11,6 @@ public class GetOssObjectInput [Required] public string Object { get; set; } + public bool MD5 { get; set; } } diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/ValidationOssObjectInput.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/ValidationOssObjectInput.cs new file mode 100644 index 000000000..235bc2841 --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/ValidationOssObjectInput.cs @@ -0,0 +1,28 @@ +using System.ComponentModel.DataAnnotations; + +namespace LINGYUN.Abp.OssManagement; + +public class ValidationOssObjectInput +{ + /// + /// 总文件大小 + /// + [Required] + public long TotalSize { get; set; } + /// + /// 文件名 + /// + [Required] + public string FileName { get; set; } + /// + /// 容器 + /// + [Required] + public string Bucket { get; set; } + /// + /// 路径 + /// + public string Path { get; set; } + + public bool Overwrite { get; set; } +} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileUploadMerger.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileUploadMerger.cs index ec0aff509..fdefe79a5 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileUploadMerger.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileUploadMerger.cs @@ -4,8 +4,8 @@ using LINGYUN.Abp.OssManagement.Localization; using Microsoft.Extensions.Localization; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.IO; using System.Threading.Tasks; +using Volo.Abp; using Volo.Abp.DependencyInjection; using Volo.Abp.Features; using Volo.Abp.Validation; @@ -65,6 +65,25 @@ public class FileUploadMerger : ITransientDependency return await oss.CreateObjectAsync(createOssObjectRequest); } + public async virtual Task ValidationAsync(ValidationOssObjectInput input) + { + await _fileValidater.ValidationAsync(new UploadFile + { + TotalSize = input.TotalSize, + FileName = input.FileName + }); + + var oss = CreateOssContainer(); + + if (!input.Overwrite && await oss.ObjectExistsAsync(new GetOssObjectRequest( + input.Bucket, + input.FileName, + input.Path))) + { + throw new BusinessException(OssManagementErrorCodes.ObjectAlreadyExists); + } + } + protected virtual IOssContainer CreateOssContainer() { return _ossContainerFactory.Create(); diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileUploader.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileUploader.cs index 442f81690..93af01a04 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileUploader.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileUploader.cs @@ -10,20 +10,22 @@ namespace LINGYUN.Abp.OssManagement; public class FileUploader : IFileUploader, ITransientDependency { - private readonly IFileValidater _fileValidater; private readonly FileUploadMerger _fileUploadMerger; - public FileUploader( - IFileValidater fileValidater, - FileUploadMerger fileUploadMerger) + public FileUploader(FileUploadMerger fileUploadMerger) { - _fileValidater = fileValidater; _fileUploadMerger = fileUploadMerger; } public async virtual Task UploadAsync(UploadFileChunkInput input, CancellationToken cancellationToken = default) { - await _fileValidater.ValidationAsync(input); + await _fileUploadMerger.ValidationAsync(new ValidationOssObjectInput + { + TotalSize = input.TotalSize, + FileName = input.FileName, + Bucket = input.Bucket, + Path = input.Path, + }); // 以上传的文件名创建一个临时目录 var tempFilePath = Path.Combine( Path.GetTempPath(), From da43ad944a4ade920b27a624bbc29b497ccf802d Mon Sep 17 00:00:00 2001 From: colin Date: Mon, 28 Apr 2025 20:13:44 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix(oss):=20=E4=BF=AE=E5=A4=8D=E6=89=A9?= =?UTF-8?q?=E5=B1=95=E6=8E=A5=E5=8F=A3=E5=90=8D=E7=A7=B0=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AliyunOssContainerServiceCollectionExtensions.cs | 2 +- .../TencentOssContainerServiceCollectionExtensions.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/Microsoft/Extensions/DependencyInjection/AliyunOssContainerServiceCollectionExtensions.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/Microsoft/Extensions/DependencyInjection/AliyunOssContainerServiceCollectionExtensions.cs index bed1323a6..9f871949f 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/Microsoft/Extensions/DependencyInjection/AliyunOssContainerServiceCollectionExtensions.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/Microsoft/Extensions/DependencyInjection/AliyunOssContainerServiceCollectionExtensions.cs @@ -6,7 +6,7 @@ namespace Microsoft.Extensions.DependencyInjection; public static class AliyunOssContainerServiceCollectionExtensions { - public static IServiceCollection AddMinioContainer(this IServiceCollection services) + public static IServiceCollection AddAliyunContainer(this IServiceCollection services) { services.AddTransient(); diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Tencent/Microsoft/Extensions/DependencyInjection/TencentOssContainerServiceCollectionExtensions.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Tencent/Microsoft/Extensions/DependencyInjection/TencentOssContainerServiceCollectionExtensions.cs index bb4fc05ae..7f672e7d4 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Tencent/Microsoft/Extensions/DependencyInjection/TencentOssContainerServiceCollectionExtensions.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Tencent/Microsoft/Extensions/DependencyInjection/TencentOssContainerServiceCollectionExtensions.cs @@ -6,7 +6,7 @@ namespace Microsoft.Extensions.DependencyInjection; public static class TencentOssContainerServiceCollectionExtensions { - public static IServiceCollection AddMinioContainer(this IServiceCollection services) + public static IServiceCollection AddTencentContainer(this IServiceCollection services) { services.AddTransient(); From 43e312eee6747c2baf251e55bf47c9c659e94874 Mon Sep 17 00:00:00 2001 From: colin Date: Mon, 28 Apr 2025 20:14:29 +0800 Subject: [PATCH 4/4] =?UTF-8?q?feat(oss):=20=E4=BD=BF=E7=94=A8=E4=B8=B4?= =?UTF-8?q?=E6=97=B6=E9=93=BE=E6=8E=A5=E4=B8=8B=E8=BD=BD=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Abp/OssManagement/IOssObjectAppService.cs | 49 +++++++++++++------ .../Abp/OssManagement/OssObjectAppService.cs | 45 ++++++++++++++++- .../OssManagement/OssObjectUrlCacheItem.cs | 24 +++++++++ .../Localization/Resources/en.json | 1 + .../Localization/Resources/zh-Hans.json | 1 + .../OssManagement/OssManagementErrorCodes.cs | 1 + 6 files changed, 103 insertions(+), 18 deletions(-) create mode 100644 aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectUrlCacheItem.cs diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/IOssObjectAppService.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/IOssObjectAppService.cs index 9120313f9..d3e427015 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/IOssObjectAppService.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/IOssObjectAppService.cs @@ -1,18 +1,35 @@ -using System.Threading.Tasks; -using Volo.Abp.Application.Services; +using System; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; using Volo.Abp.Content; -namespace LINGYUN.Abp.OssManagement; - -public interface IOssObjectAppService : IApplicationService -{ - Task CreateAsync(CreateOssObjectInput input); - - Task GetAsync(GetOssObjectInput input); - - Task GetContentAsync(GetOssObjectInput input); - - Task DeleteAsync(GetOssObjectInput input); - - Task BulkDeleteAsync(BulkDeleteOssObjectInput input); -} +namespace LINGYUN.Abp.OssManagement; + +public interface IOssObjectAppService : IApplicationService +{ + Task CreateAsync(CreateOssObjectInput input); + + Task GetAsync(GetOssObjectInput input); + /// + /// 生成下载链接 + /// + /// + /// 由于a标签无法传递token, 由后端生成一次性下载链接 + /// + /// + /// + Task GenerateUrlAsync(GetOssObjectInput input); + /// + /// 下载文件 + /// + /// 生成的一次性链接key + /// + Task DownloadAsync(string urlKey); + + [Obsolete("请使用 GenerateUrlAsync 与 DownloadAsync的组合")] + Task GetContentAsync(GetOssObjectInput input); + + Task DeleteAsync(GetOssObjectInput input); + + Task BulkDeleteAsync(BulkDeleteOssObjectInput input); +} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectAppService.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectAppService.cs index 3e039b5b3..c4d2b1f66 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectAppService.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectAppService.cs @@ -1,24 +1,33 @@ using LINGYUN.Abp.OssManagement.Permissions; using Microsoft.AspNetCore.Authorization; +using System; using System.IO; using System.Threading.Tasks; using System.Web; +using Volo.Abp; +using Volo.Abp.Caching; using Volo.Abp.Content; +using Volo.Abp.Json; namespace LINGYUN.Abp.OssManagement; -[Authorize(AbpOssManagementPermissions.OssObject.Default)] public class OssObjectAppService : OssManagementApplicationServiceBase, IOssObjectAppService { protected FileUploadMerger Merger { get; } protected IOssContainerFactory OssContainerFactory { get; } + protected IDistributedCache UrlCache { get; } + protected IJsonSerializer JsonSerializer { get; } public OssObjectAppService( FileUploadMerger merger, - IOssContainerFactory ossContainerFactory) + IJsonSerializer jsonSerializer, + IOssContainerFactory ossContainerFactory, + IDistributedCache urlCache) { Merger = merger; + JsonSerializer = jsonSerializer; OssContainerFactory = ossContainerFactory; + UrlCache = urlCache; } [Authorize(AbpOssManagementPermissions.OssObject.Create)] @@ -61,6 +70,7 @@ public class OssObjectAppService : OssManagementApplicationServiceBase, IOssObje await oss.DeleteObjectAsync(input.Bucket, input.Object, input.Path); } + [Authorize(AbpOssManagementPermissions.OssObject.Default)] public async virtual Task GetAsync(GetOssObjectInput input) { var oss = CreateOssContainer(); @@ -70,6 +80,7 @@ public class OssObjectAppService : OssManagementApplicationServiceBase, IOssObje return ObjectMapper.Map(ossObject); } + [Authorize(AbpOssManagementPermissions.OssObject.Download)] public async virtual Task GetContentAsync(GetOssObjectInput input) { var oss = CreateOssContainer(); @@ -83,4 +94,34 @@ public class OssObjectAppService : OssManagementApplicationServiceBase, IOssObje { return OssContainerFactory.Create(); } + + [Authorize(AbpOssManagementPermissions.OssObject.Download)] + public async virtual Task GenerateUrlAsync(GetOssObjectInput input) + { + var cacheKey = JsonSerializer.Serialize(input).ToMd5(); + var cacheItem = await UrlCache.GetAsync(cacheKey); + if (cacheItem == null) + { + var url = $"/api/oss-management/objects/download/{cacheKey}"; + cacheItem = new OssObjectUrlCacheItem(url, input.Bucket, input.Path, input.Object); + + await UrlCache.SetAsync(cacheKey, cacheItem); + } + + return cacheItem.Url; + } + + public async virtual Task DownloadAsync(string urlKey) + { + var cacheItem = await UrlCache.GetAsync(urlKey) ?? + throw new BusinessException(OssManagementErrorCodes.ObjectUrlKeyHasExpired); + + await UrlCache.RemoveAsync(urlKey); + + var oss = CreateOssContainer(); + + var ossObject = await oss.GetObjectAsync(cacheItem.Bucket, cacheItem.Object, cacheItem.Path); + + return new RemoteStreamContent(ossObject.Content, ossObject.Name); + } } diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectUrlCacheItem.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectUrlCacheItem.cs new file mode 100644 index 000000000..f7d25795e --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectUrlCacheItem.cs @@ -0,0 +1,24 @@ +namespace LINGYUN.Abp.OssManagement; + +public class OssObjectUrlCacheItem +{ + public string Url { get; set; } + + public string Bucket { get; set; } + + public string Path { get; set; } + + public string Object { get; set; } + public OssObjectUrlCacheItem() + { + + } + + public OssObjectUrlCacheItem(string url, string bucket, string path, string @object) + { + Url = url; + Bucket = bucket; + Path = path; + Object = @object; + } +} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/en.json b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/en.json index 93424303f..3199da6c9 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/en.json +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/en.json @@ -8,6 +8,7 @@ "Abp.OssManagement:020001": "An object that has more than one child cannot be deleted!", "Abp.OssManagement:020402": "The object name already exists!", "Abp.OssManagement:020404": "The queried object could not be found!", + "Abp.OssManagement:020405": "The download link has expired!", "Abp.OssManagement:000405": "The path object name has exceeded the allowable maximum length and cannot continue to create a new object!", "Permission:OssManagement": "Object Storage", "Permission:Container": "Containers", diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/zh-Hans.json b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/zh-Hans.json index 1995ccee3..6cbd2f8fb 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/zh-Hans.json +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/zh-Hans.json @@ -8,6 +8,7 @@ "Abp.OssManagement:020001": "不能删除存在多个子级的对象!", "Abp.OssManagement:020402": "对象名称已经存在!", "Abp.OssManagement:020404": "未能找到查询的对象!", + "Abp.OssManagement:020405": "下载链接已失效!", "Abp.OssManagement:000405": "此路径对象名称已超出允许的最大长度,无法继续创建新对象!", "Permission:OssManagement": "对象存储", "Permission:Container": "容器管理", diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/OssManagementErrorCodes.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/OssManagementErrorCodes.cs index 59f623618..2370ef45c 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/OssManagementErrorCodes.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/OssManagementErrorCodes.cs @@ -12,6 +12,7 @@ public static class OssManagementErrorCodes public const string ObjectDeleteWithNotEmpty = Namespace + ":020001"; public const string ObjectAlreadyExists = Namespace + ":020402"; public const string ObjectNotFound = Namespace + ":020404"; + public const string ObjectUrlKeyHasExpired = Namespace + ":020405"; public const string OssNameHasTooLong = Namespace + ":000405"; }