From 43e312eee6747c2baf251e55bf47c9c659e94874 Mon Sep 17 00:00:00 2001 From: colin Date: Mon, 28 Apr 2025 20:14:29 +0800 Subject: [PATCH] =?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"; }