Browse Source

Merge pull request #1192 from colinin/enhance-oss

feat(oss): Enhance oss management
pull/1211/head
yx lin 1 year ago
committed by GitHub
parent
commit
6d9e050285
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 13
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/LINGYUN/Abp/OssManagement/Aliyun/AliyunOssContainer.cs
  2. 2
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/Microsoft/Extensions/DependencyInjection/AliyunOssContainerServiceCollectionExtensions.cs
  3. 1
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/GetOssObjectInput.cs
  4. 49
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/IOssObjectAppService.cs
  5. 28
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/ValidationOssObjectInput.cs
  6. 21
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileUploadMerger.cs
  7. 14
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileUploader.cs
  8. 45
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectAppService.cs
  9. 24
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectUrlCacheItem.cs
  10. 1
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/en.json
  11. 1
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/zh-Hans.json
  12. 1
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/OssManagementErrorCodes.cs
  13. 6
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/IOssContainer.cs
  14. 2
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/OssContainerBase.cs
  15. 16
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/FileSystemOssContainer.cs
  16. 46
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/OssObjectController.cs
  17. 14
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Minio/LINGYUN/Abp/OssManagement/Minio/MinioOssContainer.cs
  18. 16
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Nexus/LINGYUN/Abp/OssManagement/Nexus/NexusOssContainer.cs
  19. 13
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Tencent/LINGYUN/Abp/OssManagement/Tencent/TencentOssContainer.cs
  20. 2
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Tencent/Microsoft/Extensions/DependencyInjection/TencentOssContainerServiceCollectionExtensions.cs

13
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<bool> 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<OssObject> CreateObjectAsync(CreateOssObjectRequest request)
{
var ossClient = await CreateClientAsync();

2
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<IOssContainerFactory, AliyunOssContainerFactory>();

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

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

28
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
{
/// <summary>
/// 总文件大小
/// </summary>
[Required]
public long TotalSize { get; set; }
/// <summary>
/// 文件名
/// </summary>
[Required]
public string FileName { get; set; }
/// <summary>
/// 容器
/// </summary>
[Required]
public string Bucket { get; set; }
/// <summary>
/// 路径
/// </summary>
public string Path { get; set; }
public bool Overwrite { get; set; }
}

21
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();

14
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(),

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

6
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/IOssContainer.cs

@ -60,6 +60,12 @@ public interface IOssContainer
/// <returns></returns>
Task<bool> ExistsAsync(string name);
/// <summary>
/// Oss对象是否存在
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
Task<bool> ObjectExistsAsync(GetOssObjectRequest request);
/// <summary>
/// 获取容器列表
/// </summary>
/// <param name="request"></param>

2
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<bool> ObjectExistsAsync(GetOssObjectRequest request);
}

16
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<bool> 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<OssObject> CreateObjectAsync(CreateOssObjectRequest request)
{
var objectPath = !request.Path.IsNullOrWhiteSpace()

46
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<OssObjectDto> CreateAsync([FromForm] CreateOssObjectInput input)
[Authorize(AbpOssManagementPermissions.OssObject.Create)]
public virtual Task<OssObjectDto> 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<OssObjectDto> GetAsync(GetOssObjectInput input)
[Authorize(AbpOssManagementPermissions.OssObject.Default)]
public virtual Task<OssObjectDto> GetAsync(GetOssObjectInput input)
{
return await OssObjectAppService.GetAsync(input);
return OssObjectAppService.GetAsync(input);
}
[HttpGet]
[Route("download")]
public async virtual Task<IRemoteStreamContent> GetContentAsync(GetOssObjectInput input)
[Authorize(AbpOssManagementPermissions.OssObject.Download)]
[Obsolete("请使用 GenerateUrlAsync 与 DownloadAsync的组合")]
public virtual Task<IRemoteStreamContent> GetContentAsync(GetOssObjectInput input)
{
return OssObjectAppService.GetContentAsync(input);
}
[HttpGet]
[Route("generate-url")]
[Authorize(AbpOssManagementPermissions.OssObject.Download)]
public virtual Task<string> GenerateUrlAsync(GetOssObjectInput input)
{
return OssObjectAppService.GenerateUrlAsync(input);
}
[HttpGet]
[Route("download/{urlKey}")]
public virtual Task<IRemoteStreamContent> DownloadAsync(string urlKey)
{
return await OssObjectAppService.GetContentAsync(input);
return OssObjectAppService.DownloadAsync(urlKey);
}
}

14
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<string, string>());
}
public async override Task<bool> 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<OssObject> CreateObjectAsync(CreateOssObjectRequest request)
{
var client = GetMinioClient();

16
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<bool> 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<OssObject> CreateObjectAsync(CreateOssObjectRequest request)
{
var nexusConfiguration = GetNexusConfiguration();

13
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<bool> 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<OssObject> CreateObjectAsync(CreateOssObjectRequest request)
{
var ossClient = await CreateClientAsync();

2
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<IOssContainerFactory, TencentOssContainerFactory>();

Loading…
Cancel
Save