Browse Source

feat(oss): 使用临时链接下载文件

pull/1192/head
colin 11 months ago
parent
commit
43e312eee6
  1. 49
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/IOssObjectAppService.cs
  2. 45
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectAppService.cs
  3. 24
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectUrlCacheItem.cs
  4. 1
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/en.json
  5. 1
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/zh-Hans.json
  6. 1
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/OssManagementErrorCodes.cs

49
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<OssObjectDto> CreateAsync(CreateOssObjectInput input);
Task<OssObjectDto> GetAsync(GetOssObjectInput input);
Task<IRemoteStreamContent> GetContentAsync(GetOssObjectInput input);
Task DeleteAsync(GetOssObjectInput input);
Task BulkDeleteAsync(BulkDeleteOssObjectInput input);
}
namespace LINGYUN.Abp.OssManagement;
public interface IOssObjectAppService : IApplicationService
{
Task<OssObjectDto> CreateAsync(CreateOssObjectInput input);
Task<OssObjectDto> GetAsync(GetOssObjectInput input);
/// <summary>
/// 生成下载链接
/// </summary>
/// <remarks>
/// 由于a标签无法传递token, 由后端生成一次性下载链接
/// </remarks>
/// <param name="input"></param>
/// <returns></returns>
Task<string> GenerateUrlAsync(GetOssObjectInput input);
/// <summary>
/// 下载文件
/// </summary>
/// <param name="urlKey">生成的一次性链接key</param>
/// <returns></returns>
Task<IRemoteStreamContent> DownloadAsync(string urlKey);
[Obsolete("请使用 GenerateUrlAsync 与 DownloadAsync的组合")]
Task<IRemoteStreamContent> GetContentAsync(GetOssObjectInput input);
Task DeleteAsync(GetOssObjectInput input);
Task BulkDeleteAsync(BulkDeleteOssObjectInput input);
}

45
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<OssObjectUrlCacheItem> UrlCache { get; }
protected IJsonSerializer JsonSerializer { get; }
public OssObjectAppService(
FileUploadMerger merger,
IOssContainerFactory ossContainerFactory)
IJsonSerializer jsonSerializer,
IOssContainerFactory ossContainerFactory,
IDistributedCache<OssObjectUrlCacheItem> 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<OssObjectDto> GetAsync(GetOssObjectInput input)
{
var oss = CreateOssContainer();
@ -70,6 +80,7 @@ public class OssObjectAppService : OssManagementApplicationServiceBase, IOssObje
return ObjectMapper.Map<OssObject, OssObjectDto>(ossObject);
}
[Authorize(AbpOssManagementPermissions.OssObject.Download)]
public async virtual Task<IRemoteStreamContent> 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<string> 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<IRemoteStreamContent> 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);
}
}

24
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;
}
}

1
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",

1
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": "容器管理",

1
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";
}

Loading…
Cancel
Save