|
|
@ -1,5 +1,7 @@ |
|
|
using Microsoft.Extensions.Configuration; |
|
|
using Microsoft.Extensions.Configuration; |
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection; |
|
|
using Microsoft.Extensions.Logging; |
|
|
using Microsoft.Extensions.Logging; |
|
|
|
|
|
using Microsoft.Extensions.Options; |
|
|
using Minio; |
|
|
using Minio; |
|
|
using Minio.DataModel.Args; |
|
|
using Minio.DataModel.Args; |
|
|
using Minio.DataModel.ILM; |
|
|
using Minio.DataModel.ILM; |
|
|
@ -22,7 +24,7 @@ namespace LINGYUN.Abp.OssManagement.Minio; |
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// Oss容器的Minio实现
|
|
|
/// Oss容器的Minio实现
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
public class MinioOssContainer : IOssContainer, IOssObjectExpireor |
|
|
public class MinioOssContainer : OssContainerBase, IOssObjectExpireor |
|
|
{ |
|
|
{ |
|
|
protected IMinioBlobNameCalculator MinioBlobNameCalculator { get; } |
|
|
protected IMinioBlobNameCalculator MinioBlobNameCalculator { get; } |
|
|
protected IBlobNormalizeNamingService BlobNormalizeNamingService { get; } |
|
|
protected IBlobNormalizeNamingService BlobNormalizeNamingService { get; } |
|
|
@ -38,7 +40,10 @@ public class MinioOssContainer : IOssContainer, IOssObjectExpireor |
|
|
ILogger<MinioOssContainer> logger, |
|
|
ILogger<MinioOssContainer> logger, |
|
|
IMinioBlobNameCalculator minioBlobNameCalculator, |
|
|
IMinioBlobNameCalculator minioBlobNameCalculator, |
|
|
IBlobNormalizeNamingService blobNormalizeNamingService, |
|
|
IBlobNormalizeNamingService blobNormalizeNamingService, |
|
|
IBlobContainerConfigurationProvider configurationProvider) |
|
|
IBlobContainerConfigurationProvider configurationProvider, |
|
|
|
|
|
IServiceScopeFactory serviceScopeFactory, |
|
|
|
|
|
IOptions<AbpOssManagementOptions> options) |
|
|
|
|
|
: base(options, serviceScopeFactory) |
|
|
{ |
|
|
{ |
|
|
Clock = clock; |
|
|
Clock = clock; |
|
|
Logger = logger; |
|
|
Logger = logger; |
|
|
@ -48,7 +53,7 @@ public class MinioOssContainer : IOssContainer, IOssObjectExpireor |
|
|
ConfigurationProvider = configurationProvider; |
|
|
ConfigurationProvider = configurationProvider; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async virtual Task BulkDeleteObjectsAsync(BulkDeleteObjectRequest request) |
|
|
public async override Task BulkDeleteObjectsAsync(BulkDeleteObjectRequest request) |
|
|
{ |
|
|
{ |
|
|
var client = GetMinioClient(); |
|
|
var client = GetMinioClient(); |
|
|
|
|
|
|
|
|
@ -76,7 +81,7 @@ public class MinioOssContainer : IOssContainer, IOssObjectExpireor |
|
|
await tcs.Task; |
|
|
await tcs.Task; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async virtual Task<OssContainer> CreateAsync(string name) |
|
|
public async override Task<OssContainer> CreateAsync(string name) |
|
|
{ |
|
|
{ |
|
|
var client = GetMinioClient(); |
|
|
var client = GetMinioClient(); |
|
|
|
|
|
|
|
|
@ -97,7 +102,7 @@ public class MinioOssContainer : IOssContainer, IOssObjectExpireor |
|
|
new Dictionary<string, string>()); |
|
|
new Dictionary<string, string>()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async virtual Task<OssObject> CreateObjectAsync(CreateOssObjectRequest request) |
|
|
public async override Task<OssObject> CreateObjectAsync(CreateOssObjectRequest request) |
|
|
{ |
|
|
{ |
|
|
var client = GetMinioClient(); |
|
|
var client = GetMinioClient(); |
|
|
|
|
|
|
|
|
@ -176,46 +181,7 @@ public class MinioOssContainer : IOssContainer, IOssObjectExpireor |
|
|
return ossObject; |
|
|
return ossObject; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async virtual Task DeleteAsync(string name) |
|
|
public async override Task DeleteObjectAsync(GetOssObjectRequest request) |
|
|
{ |
|
|
|
|
|
var client = GetMinioClient(); |
|
|
|
|
|
var bucket = GetBucket(name); |
|
|
|
|
|
|
|
|
|
|
|
if (!await BucketExists(client, bucket)) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new BusinessException(code: OssManagementErrorCodes.ContainerNotFound); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 非空目录无法删除
|
|
|
|
|
|
var tcs = new TaskCompletionSource<bool>(); |
|
|
|
|
|
var listObjectObs = client.ListObjectsAsync( |
|
|
|
|
|
new ListObjectsArgs() |
|
|
|
|
|
.WithBucket(bucket)); |
|
|
|
|
|
|
|
|
|
|
|
var listObjects = new List<string>(); |
|
|
|
|
|
using var _ = listObjectObs.Subscribe( |
|
|
|
|
|
(item) => |
|
|
|
|
|
{ |
|
|
|
|
|
listObjects.Add(item.Key); |
|
|
|
|
|
tcs.TrySetResult(true); |
|
|
|
|
|
}, |
|
|
|
|
|
(ex) => tcs.TrySetException(ex), |
|
|
|
|
|
() => tcs.TrySetResult(true)); |
|
|
|
|
|
|
|
|
|
|
|
await tcs.Task; |
|
|
|
|
|
|
|
|
|
|
|
if (listObjects.Count > 0) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new BusinessException(code: OssManagementErrorCodes.ContainerDeleteWithNotEmpty); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var deleteBucketArgs = new RemoveBucketArgs() |
|
|
|
|
|
.WithBucket(bucket); |
|
|
|
|
|
|
|
|
|
|
|
await client.RemoveBucketAsync(deleteBucketArgs); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async virtual Task DeleteObjectAsync(GetOssObjectRequest request) |
|
|
|
|
|
{ |
|
|
{ |
|
|
if (request.Object.EndsWith('/')) |
|
|
if (request.Object.EndsWith('/')) |
|
|
{ |
|
|
{ |
|
|
@ -245,7 +211,7 @@ public class MinioOssContainer : IOssContainer, IOssObjectExpireor |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async virtual Task<bool> ExistsAsync(string name) |
|
|
public async override Task<bool> ExistsAsync(string name) |
|
|
{ |
|
|
{ |
|
|
var client = GetMinioClient(); |
|
|
var client = GetMinioClient(); |
|
|
|
|
|
|
|
|
@ -297,7 +263,7 @@ public class MinioOssContainer : IOssContainer, IOssObjectExpireor |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async virtual Task<OssContainer> GetAsync(string name) |
|
|
public async override Task<OssContainer> GetAsync(string name) |
|
|
{ |
|
|
{ |
|
|
var client = GetMinioClient(); |
|
|
var client = GetMinioClient(); |
|
|
|
|
|
|
|
|
@ -319,7 +285,7 @@ public class MinioOssContainer : IOssContainer, IOssObjectExpireor |
|
|
new Dictionary<string, string>()); |
|
|
new Dictionary<string, string>()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async virtual Task<GetOssContainersResponse> GetListAsync(GetOssContainersRequest request) |
|
|
public async override Task<GetOssContainersResponse> GetListAsync(GetOssContainersRequest request) |
|
|
{ |
|
|
{ |
|
|
var client = GetMinioClient(); |
|
|
var client = GetMinioClient(); |
|
|
|
|
|
|
|
|
@ -347,70 +313,7 @@ public class MinioOssContainer : IOssContainer, IOssObjectExpireor |
|
|
resultObjects); |
|
|
resultObjects); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public async virtual Task<OssObject> GetObjectAsync(GetOssObjectRequest request) |
|
|
public async override Task<GetOssObjectsResponse> GetObjectsAsync(GetOssObjectsRequest 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.EnsureEndsWith('/') + request.Object; |
|
|
|
|
|
|
|
|
|
|
|
if (!await ObjectExists(client, bucket, objectName)) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new BusinessException(code: OssManagementErrorCodes.ObjectNotFound); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var memoryStream = new MemoryStream(); |
|
|
|
|
|
var getObjectArgs = new GetObjectArgs() |
|
|
|
|
|
.WithBucket(bucket) |
|
|
|
|
|
.WithObject(objectName) |
|
|
|
|
|
.WithCallbackStream((stream) => |
|
|
|
|
|
{ |
|
|
|
|
|
if (stream != null) |
|
|
|
|
|
{ |
|
|
|
|
|
stream.CopyTo(memoryStream); |
|
|
|
|
|
memoryStream.Seek(0, SeekOrigin.Begin); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
memoryStream = null; |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
var getObjectResult = await client.GetObjectAsync(getObjectArgs); |
|
|
|
|
|
|
|
|
|
|
|
var ossObject = new OssObject( |
|
|
|
|
|
!objectPath.IsNullOrWhiteSpace() |
|
|
|
|
|
? getObjectResult.ObjectName.Replace(objectPath, "") |
|
|
|
|
|
: getObjectResult.ObjectName, |
|
|
|
|
|
request.Path, |
|
|
|
|
|
getObjectResult.ETag, |
|
|
|
|
|
getObjectResult.LastModified, |
|
|
|
|
|
memoryStream.Length, |
|
|
|
|
|
getObjectResult.LastModified, |
|
|
|
|
|
getObjectResult.MetaData, |
|
|
|
|
|
getObjectResult.ObjectName.EndsWith("/")) |
|
|
|
|
|
{ |
|
|
|
|
|
FullName = getObjectResult.ObjectName.Replace(prefixPath, "") |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
if (memoryStream.Length > 0) |
|
|
|
|
|
{ |
|
|
|
|
|
ossObject.SetContent(memoryStream); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!request.Process.IsNullOrWhiteSpace()) |
|
|
|
|
|
{ |
|
|
|
|
|
// TODO: 文件流处理
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return ossObject; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async virtual Task<GetOssObjectsResponse> GetObjectsAsync(GetOssObjectsRequest request) |
|
|
|
|
|
{ |
|
|
{ |
|
|
var client = GetMinioClient(); |
|
|
var client = GetMinioClient(); |
|
|
|
|
|
|
|
|
@ -476,6 +379,103 @@ public class MinioOssContainer : IOssContainer, IOssObjectExpireor |
|
|
resultObjects); |
|
|
resultObjects); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected async override Task DeleteBucketAsync(string name) |
|
|
|
|
|
{ |
|
|
|
|
|
var client = GetMinioClient(); |
|
|
|
|
|
var bucket = GetBucket(name); |
|
|
|
|
|
|
|
|
|
|
|
if (!await BucketExists(client, bucket)) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new BusinessException(code: OssManagementErrorCodes.ContainerNotFound); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 非空目录无法删除
|
|
|
|
|
|
var tcs = new TaskCompletionSource<bool>(); |
|
|
|
|
|
var listObjectObs = client.ListObjectsAsync( |
|
|
|
|
|
new ListObjectsArgs() |
|
|
|
|
|
.WithBucket(bucket)); |
|
|
|
|
|
|
|
|
|
|
|
var listObjects = new List<string>(); |
|
|
|
|
|
using var _ = listObjectObs.Subscribe( |
|
|
|
|
|
(item) => |
|
|
|
|
|
{ |
|
|
|
|
|
listObjects.Add(item.Key); |
|
|
|
|
|
tcs.TrySetResult(true); |
|
|
|
|
|
}, |
|
|
|
|
|
(ex) => tcs.TrySetException(ex), |
|
|
|
|
|
() => tcs.TrySetResult(true)); |
|
|
|
|
|
|
|
|
|
|
|
await tcs.Task; |
|
|
|
|
|
|
|
|
|
|
|
if (listObjects.Count > 0) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new BusinessException(code: OssManagementErrorCodes.ContainerDeleteWithNotEmpty); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var deleteBucketArgs = new RemoveBucketArgs() |
|
|
|
|
|
.WithBucket(bucket); |
|
|
|
|
|
|
|
|
|
|
|
await client.RemoveBucketAsync(deleteBucketArgs); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected async override Task<OssObject> GetOssObjectAsync(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.EnsureEndsWith('/') + request.Object; |
|
|
|
|
|
|
|
|
|
|
|
if (!await ObjectExists(client, bucket, objectName)) |
|
|
|
|
|
{ |
|
|
|
|
|
throw new BusinessException(code: OssManagementErrorCodes.ObjectNotFound); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var memoryStream = new MemoryStream(); |
|
|
|
|
|
var getObjectArgs = new GetObjectArgs() |
|
|
|
|
|
.WithBucket(bucket) |
|
|
|
|
|
.WithObject(objectName) |
|
|
|
|
|
.WithCallbackStream((stream) => |
|
|
|
|
|
{ |
|
|
|
|
|
if (stream != null) |
|
|
|
|
|
{ |
|
|
|
|
|
stream.CopyTo(memoryStream); |
|
|
|
|
|
memoryStream.Seek(0, SeekOrigin.Begin); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
memoryStream = null; |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
var getObjectResult = await client.GetObjectAsync(getObjectArgs); |
|
|
|
|
|
|
|
|
|
|
|
var ossObject = new OssObject( |
|
|
|
|
|
!objectPath.IsNullOrWhiteSpace() |
|
|
|
|
|
? getObjectResult.ObjectName.Replace(objectPath, "") |
|
|
|
|
|
: getObjectResult.ObjectName, |
|
|
|
|
|
request.Path, |
|
|
|
|
|
getObjectResult.ETag, |
|
|
|
|
|
getObjectResult.LastModified, |
|
|
|
|
|
memoryStream.Length, |
|
|
|
|
|
getObjectResult.LastModified, |
|
|
|
|
|
getObjectResult.MetaData, |
|
|
|
|
|
getObjectResult.ObjectName.EndsWith("/")) |
|
|
|
|
|
{ |
|
|
|
|
|
FullName = getObjectResult.ObjectName.Replace(prefixPath, "") |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
if (memoryStream.Length > 0) |
|
|
|
|
|
{ |
|
|
|
|
|
ossObject.SetContent(memoryStream); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return ossObject; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
protected virtual IMinioClient GetMinioClient() |
|
|
protected virtual IMinioClient GetMinioClient() |
|
|
{ |
|
|
{ |
|
|
var configuration = GetMinioConfiguration(); |
|
|
var configuration = GetMinioConfiguration(); |
|
|
|