diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobNamingNormalizer.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobNamingNormalizer.cs index 0e9e338d7..9e7b60f63 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobNamingNormalizer.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobNamingNormalizer.cs @@ -1,5 +1,4 @@ -using System; -using Volo.Abp.BlobStoring; +using Volo.Abp.BlobStoring; using Volo.Abp.DependencyInjection; namespace LINGYUN.Abp.BlobStoring.OssManagement; @@ -13,8 +12,7 @@ public class OssManagementBlobNamingNormalizer : IBlobNamingNormalizer, ITransie public virtual string NormalizeContainerName(string containerName) { - // 尾部添加反斜杠 - return NormalizeName(containerName).EnsureEndsWith('/'); + return NormalizeName(containerName); } protected virtual string NormalizeName(string name) diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobProvider.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobProvider.cs index c14164118..4e2af27be 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobProvider.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobProvider.cs @@ -26,10 +26,9 @@ public class OssManagementBlobProvider : BlobProviderBase, ITransientDependency public override async Task DeleteAsync(BlobProviderDeleteArgs args) { - var configuration = args.Configuration.GetOssManagementConfiguration(); await _ossObjectAppService.DeleteAsync(new GetOssObjectInput { - Bucket = configuration.Bucket, + Bucket = args.ContainerName, Path = GetOssPath(args), Object = GetOssName(args), }); @@ -38,10 +37,9 @@ public class OssManagementBlobProvider : BlobProviderBase, ITransientDependency public override async Task ExistsAsync(BlobProviderExistsArgs args) { - var configuration = args.Configuration.GetOssManagementConfiguration(); var result = await _ossObjectAppService.ExistsAsync(new GetOssObjectInput { - Bucket = configuration.Bucket, + Bucket = args.ContainerName, Path = GetOssPath(args), Object = GetOssName(args), }); @@ -50,10 +48,9 @@ public class OssManagementBlobProvider : BlobProviderBase, ITransientDependency public override async Task GetOrNullAsync(BlobProviderGetArgs args) { - var configuration = args.Configuration.GetOssManagementConfiguration(); var content = await _ossObjectAppService.GetAsync(new GetOssObjectInput { - Bucket = configuration.Bucket, + Bucket = args.ContainerName, Path = GetOssPath(args), Object = GetOssName(args), }); @@ -63,10 +60,9 @@ public class OssManagementBlobProvider : BlobProviderBase, ITransientDependency public override async Task SaveAsync(BlobProviderSaveArgs args) { - var configuration = args.Configuration.GetOssManagementConfiguration(); await _ossObjectAppService.CreateAsync(new CreateOssObjectInput { - Bucket = configuration.Bucket, + Bucket = args.ContainerName, Overwrite = args.OverrideExisting, Path = GetOssPath(args), FileName = GetOssName(args), @@ -76,16 +72,14 @@ public class OssManagementBlobProvider : BlobProviderBase, ITransientDependency protected virtual string GetOssPath(BlobProviderArgs args) { - // ContainerName: blob - // path1/path2/path3/path3/path5/file.txt => blob/path1/path2/path3/path3/path5/ - var path = args.ContainerName; + // path1/path2/path3/path3/path5/file.txt => path1/path2/path3/path3/path5/ if (args.BlobName.Contains("/")) { var lastIndex = args.BlobName.LastIndexOf('/'); - path += args.BlobName.Substring(0, lastIndex); + return args.BlobName.Substring(0, lastIndex); } - return path.EnsureEndsWith('/'); + return args.BlobName.EnsureEndsWith('/'); } protected virtual string GetOssName(BlobProviderArgs args) 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 f2378750f..be388e879 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 @@ -119,6 +119,7 @@ public class MinioOssContainer : OssContainerBase, IOssObjectExpireor var objectName = objectPath.IsNullOrWhiteSpace() ? request.Object : objectPath + request.Object; + var isDir = false; if (!request.Overwrite && await ObjectExists(client, bucket, objectName)) { @@ -137,12 +138,13 @@ public class MinioOssContainer : OssContainerBase, IOssObjectExpireor } if (request.Content.IsNullOrEmpty()) { + isDir = true; var emptyContent = "This is an OSS object that simulates a directory.".GetBytes(); request.SetContent(new MemoryStream(emptyContent)); } var putResponse = await client.PutObjectAsync(new PutObjectArgs() .WithBucket(bucket) - .WithObject(objectName) + .WithObject(isDir ? $"{objectName}/_dir" : objectName) .WithStreamData(request.Content) .WithObjectSize(request.Content.Length)); @@ -190,13 +192,6 @@ public class MinioOssContainer : OssContainerBase, IOssObjectExpireor public async override Task DeleteObjectAsync(GetOssObjectRequest request) { - if (request.Object.EndsWith('/')) - { - // Minio系统设计并不支持目录的形式 - // 如果是目录的形式,那必定有文件存在,抛出目录不为空即可 - throw new BusinessException(code: OssManagementErrorCodes.ObjectDeleteWithNotEmpty); - } - var client = GetMinioClient(); var bucket = GetBucket(request.Bucket); @@ -207,8 +202,34 @@ public class MinioOssContainer : OssContainerBase, IOssObjectExpireor ? request.Object : objectPath + request.Object; - if (await BucketExists(client, bucket) && - await ObjectExists(client, bucket, objectName)) + if (objectName.EndsWith('/') && await BucketExists(client, bucket)) + { + var objectNames = new List(); + var objects = client.ListObjectsEnumAsync( + new ListObjectsArgs() + .WithBucket(bucket) + .WithPrefix(objectName) + .WithRecursive(true)); + + await foreach (var @object in objects) + { + objectNames.Add(@object.Key); + } + + var errors = await client.RemoveObjectsAsync( + new RemoveObjectsArgs() + .WithBucket(bucket) + .WithObjects(objectNames)); + + foreach (var error in errors) + { + Logger.LogWarning("Batch deletion of objects failed, error details {code}: {message}", error.Code, error.Message); + } + + return; + } + + if (await ObjectExists(client, bucket, objectName)) { var removeObjectArgs = new RemoveObjectArgs() .WithBucket(bucket) @@ -335,6 +356,11 @@ public class MinioOssContainer : OssContainerBase, IOssObjectExpireor await foreach (var item in listObjectResult) { + // 作为目录占位,无需显示 + if (item.Key.EndsWith("_dir")) + { + continue; + } resultObjects.Add(new OssObject( !objectPath.IsNullOrWhiteSpace() ? item.Key.Replace(objectPath, "") @@ -407,7 +433,7 @@ public class MinioOssContainer : OssContainerBase, IOssObjectExpireor var objectPath = GetBlobPath(prefixPath, request.Path); var objectName = objectPath.IsNullOrWhiteSpace() ? request.Object - : objectPath.EnsureEndsWith('/') + request.Object; + : objectPath + request.Object; if (!await ObjectExists(client, bucket, objectName)) { @@ -535,6 +561,6 @@ public class MinioOssContainer : OssContainerBase, IOssObjectExpireor path.IsNullOrWhiteSpace() ? "" : path.Replace("./", "").RemovePreFix("/"))}"; - return resultPath.Replace("//", ""); + return resultPath.Replace("//", "").EnsureEndsWith('/'); } }