1300 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			1300 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C#
		
	
	
| using AlibabaCloud.SDK.Sts20150401;
 | ||
| using Aliyun.OSS;
 | ||
| using Aliyun.OSS.Common;
 | ||
| using Amazon;
 | ||
| using Amazon.Runtime;
 | ||
| using Amazon.S3;
 | ||
| using Amazon.S3.Model;
 | ||
| using Amazon.SecurityToken;
 | ||
| using Amazon.SecurityToken.Model;
 | ||
| using IRaCIS.Core.Infrastructure;
 | ||
| using IRaCIS.Core.Infrastructure.NewtonsoftJson;
 | ||
| using MassTransit;
 | ||
| using MassTransit.Caching.Internals;
 | ||
| using Microsoft.Extensions.Options;
 | ||
| using Minio;
 | ||
| using Minio.DataModel;
 | ||
| using Minio.DataModel.Args;
 | ||
| using Minio.Exceptions;
 | ||
| using System.Reactive.Linq;
 | ||
| using System.Runtime.InteropServices;
 | ||
| using System.Web;
 | ||
| 
 | ||
| namespace IRaCIS.Core.Application.Helper;
 | ||
| 
 | ||
| #region 绑定和返回模型
 | ||
| 
 | ||
| [LowerCamelCaseJson]
 | ||
| public class MinIOOptions : AWSOptions
 | ||
| {
 | ||
|     public int Port { get; set; }
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| public class AWSOptions
 | ||
| {
 | ||
|     public string EndPoint { get; set; }
 | ||
|     public bool UseSSL { get; set; }
 | ||
|     public string AccessKeyId { get; set; }
 | ||
|     public string RoleArn { get; set; }
 | ||
|     public string SecretAccessKey { get; set; }
 | ||
|     public string BucketName { get; set; }
 | ||
|     public string ViewEndpoint { get; set; }
 | ||
|     public int DurationSeconds { get; set; }
 | ||
|     public string Region { get; set; }
 | ||
| }
 | ||
| 
 | ||
| public class AliyunOSSOptions
 | ||
| {
 | ||
|     public string RegionId { get; set; }
 | ||
|     public string AccessKeyId { get; set; }
 | ||
|     public string AccessKeySecret { get; set; }
 | ||
| 
 | ||
|     public string InternalEndpoint { get; set; }
 | ||
| 
 | ||
|     public string EndPoint { get; set; }
 | ||
|     public string BucketName { get; set; }
 | ||
| 
 | ||
|     public string RoleArn { get; set; }
 | ||
| 
 | ||
|     public string Region { get; set; }
 | ||
| 
 | ||
|     public string ViewEndpoint { get; set; }
 | ||
| 
 | ||
|     public int DurationSeconds { get; set; }
 | ||
| 
 | ||
|     public string PreviewEndpoint { get; set; }
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| public class ObjectStoreServiceOptions
 | ||
| {
 | ||
|     public string ObjectStoreUse { get; set; }
 | ||
| 
 | ||
|     public AliyunOSSOptions AliyunOSS { get; set; }
 | ||
| 
 | ||
| 
 | ||
|     public MinIOOptions MinIO { get; set; }
 | ||
| 
 | ||
|     public AWSOptions AWS { get; set; }
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| public class ObjectStoreDTO
 | ||
| {
 | ||
|     public string ObjectStoreUse { get; set; }
 | ||
| 
 | ||
| 
 | ||
|     public AliyunOSSTempToken AliyunOSS { get; set; }
 | ||
| 
 | ||
|     public MinIOOptions MinIO { get; set; }
 | ||
| 
 | ||
|     public AWSTempToken AWS { get; set; }
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| [LowerCamelCaseJson]
 | ||
| public class AliyunOSSTempToken
 | ||
| {
 | ||
|     public string AccessKeyId { get; set; }
 | ||
|     public string AccessKeySecret { get; set; }
 | ||
| 
 | ||
|     public string EndPoint { get; set; }
 | ||
|     public string BucketName { get; set; }
 | ||
| 
 | ||
|     public string Region { get; set; }
 | ||
| 
 | ||
|     public string ViewEndpoint { get; set; }
 | ||
| 
 | ||
|     public string SecurityToken { get; set; }
 | ||
|     public DateTime Expiration { get; set; }
 | ||
| 
 | ||
|     public string PreviewEndpoint { get; set; }
 | ||
| 
 | ||
|     public string DownloadEndPoint => EndPoint.Insert(EndPoint.IndexOf("//") + 2, BucketName + ".");
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| [LowerCamelCaseJson]
 | ||
| public class AWSTempToken
 | ||
| {
 | ||
|     public string Region { get; set; }
 | ||
|     public string SessionToken { get; set; }
 | ||
|     public string EndPoint { get; set; }
 | ||
|     public string AccessKeyId { get; set; }
 | ||
|     public string SecretAccessKey { get; set; }
 | ||
|     public string BucketName { get; set; }
 | ||
|     public string ViewEndpoint { get; set; }
 | ||
|     public DateTime? Expiration { get; set; }
 | ||
| }
 | ||
| 
 | ||
| public enum ObjectStoreUse
 | ||
| {
 | ||
|     AliyunOSS = 0,
 | ||
|     MinIO = 1,
 | ||
|     AWS = 2,
 | ||
| }
 | ||
| 
 | ||
| #endregion
 | ||
| 
 | ||
| // aws 参考链接 https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3/S3/S3_Basics
 | ||
| 
 | ||
| public interface IOSSService
 | ||
| {
 | ||
|     public Task<string> UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true);
 | ||
|     public Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true);
 | ||
| 
 | ||
|     public Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath);
 | ||
| 
 | ||
|     public Task<Stream> GetStreamFromOSSAsync(string ossRelativePath);
 | ||
| 
 | ||
|     public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; }
 | ||
| 
 | ||
|     public Task<string> GetSignedUrl(string ossRelativePath);
 | ||
| 
 | ||
|     public Task DeleteFromPrefix(string prefix, bool isCache = false);
 | ||
| 
 | ||
|     public Task DeleteObjects(List<string> objectKeys);
 | ||
| 
 | ||
|     List<string> GetRootFolderNames();
 | ||
| 
 | ||
|     public ObjectStoreDTO GetObjectStoreTempToken();
 | ||
| 
 | ||
|     public Task MoveObject(string sourcePath, string destPath, bool overwrite = true);
 | ||
| 
 | ||
|     public Task<long> GetObjectSizeAsync(string sourcePath);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| public class OSSService : IOSSService
 | ||
| {
 | ||
|     public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; }
 | ||
| 
 | ||
|     private AliyunOSSTempToken AliyunOSSTempToken { get; set; }
 | ||
| 
 | ||
|     private AWSTempToken AWSTempToken { get; set; }
 | ||
| 
 | ||
| 
 | ||
|     public OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options)
 | ||
|     {
 | ||
|         ObjectStoreServiceOptions = options.CurrentValue;
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|     /// <summary>
 | ||
|     ///  oosFolderPath  不要 "/ "开头   应该: TempFolder/ChildFolder
 | ||
|     /// </summary>
 | ||
|     /// <param name="fileStream"></param>
 | ||
|     /// <param name="oosFolderPath"></param>
 | ||
|     /// <param name="fileRealName"></param>
 | ||
|     /// <param name="isFileNameAddGuid"></param>
 | ||
|     /// <returns></returns>
 | ||
|     public async Task<string> UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true)
 | ||
|     {
 | ||
|         BackBatchGetToken();
 | ||
| 
 | ||
|         var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{fileRealName}" : $"{oosFolderPath}/{fileRealName}";
 | ||
| 
 | ||
|         try
 | ||
|         {
 | ||
|             using (var memoryStream = new MemoryStream())
 | ||
|             {
 | ||
|                 fileStream.Seek(0, SeekOrigin.Begin);
 | ||
| 
 | ||
|                 fileStream.CopyTo(memoryStream);
 | ||
| 
 | ||
|                 memoryStream.Seek(0, SeekOrigin.Begin);
 | ||
| 
 | ||
| 
 | ||
|                 if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
 | ||
|                 {
 | ||
|                     var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
 | ||
| 
 | ||
|                     var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|                     // 上传文件
 | ||
|                     var result = _ossClient.PutObject(aliConfig.BucketName, ossRelativePath, memoryStream);
 | ||
| 
 | ||
|                 }
 | ||
|                 else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
 | ||
|                 {
 | ||
|                     var minIOConfig = ObjectStoreServiceOptions.MinIO;
 | ||
| 
 | ||
| 
 | ||
|                     var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
 | ||
|                         .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
 | ||
|                         .Build();
 | ||
| 
 | ||
|                     var putObjectArgs = new PutObjectArgs()
 | ||
|                            .WithBucket(minIOConfig.BucketName)
 | ||
|                            .WithObject(ossRelativePath)
 | ||
|                            .WithStreamData(memoryStream)
 | ||
|                            .WithObjectSize(memoryStream.Length);
 | ||
| 
 | ||
|                     await minioClient.PutObjectAsync(putObjectArgs);
 | ||
|                 }
 | ||
|                 else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
 | ||
|                 {
 | ||
|                     var awsConfig = ObjectStoreServiceOptions.AWS;
 | ||
| 
 | ||
|                     var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|                     //提供awsEndPoint(域名)进行访问配置
 | ||
|                     var clientConfig = new AmazonS3Config
 | ||
|                     {
 | ||
|                         RegionEndpoint = RegionEndpoint.USEast1,
 | ||
|                         UseHttp = true,
 | ||
|                     };
 | ||
| 
 | ||
|                     var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
 | ||
| 
 | ||
|                     var putObjectRequest = new Amazon.S3.Model.PutObjectRequest()
 | ||
|                     {
 | ||
|                         BucketName = awsConfig.BucketName,
 | ||
|                         InputStream = memoryStream,
 | ||
|                         Key = ossRelativePath,
 | ||
|                     };
 | ||
| 
 | ||
|                     await amazonS3Client.PutObjectAsync(putObjectRequest);
 | ||
|                 }
 | ||
|                 else
 | ||
|                 {
 | ||
|                     throw new BusinessValidationFailedException("未定义的存储介质类型");
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|         catch (Exception ex)
 | ||
|         {
 | ||
| 
 | ||
|             throw new BusinessValidationFailedException($"上传发生异常:{ex.Message}");
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         return "/" + ossRelativePath;
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     //后端批量上传 或者下载,不每个文件获取临时token
 | ||
|     private void BackBatchGetToken()
 | ||
|     {
 | ||
|         if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
 | ||
|         {
 | ||
|             if (AliyunOSSTempToken == null)
 | ||
|             {
 | ||
|                 GetObjectStoreTempToken();
 | ||
|             }
 | ||
|             //token 过期了
 | ||
|             if (AliyunOSSTempToken?.Expiration.AddSeconds(10) <= DateTime.Now)
 | ||
|             {
 | ||
|                 GetObjectStoreTempToken();
 | ||
|             }
 | ||
| 
 | ||
| 
 | ||
|         }
 | ||
|         else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
 | ||
|         {
 | ||
|             if (AWSTempToken == null)
 | ||
|             {
 | ||
|                 GetObjectStoreTempToken();
 | ||
|             }
 | ||
|             //token 过期了
 | ||
|             if (AWSTempToken.Expiration?.AddSeconds(10) <= DateTime.Now)
 | ||
|             {
 | ||
|                 GetObjectStoreTempToken();
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     /// <summary>
 | ||
|     /// oosFolderPath  不要 "/ "开头   应该: TempFolder/ChildFolder
 | ||
|     /// </summary>
 | ||
|     /// <param name="localFilePath"></param>
 | ||
|     /// <param name="oosFolderPath"></param>
 | ||
|     /// <param name="isFileNameAddGuid"></param>
 | ||
|     /// <returns></returns>
 | ||
|     /// <exception cref="BusinessValidationFailedException"></exception>
 | ||
|     public async Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true)
 | ||
|     {
 | ||
|         BackBatchGetToken();
 | ||
| 
 | ||
|         var localFileName = Path.GetFileName(localFilePath);
 | ||
| 
 | ||
|         var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{localFileName}" : $"{oosFolderPath}/{localFileName}";
 | ||
| 
 | ||
| 
 | ||
|         if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
 | ||
|         {
 | ||
|             var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
 | ||
| 
 | ||
|             var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
 | ||
| 
 | ||
|             // 上传文件
 | ||
|             var result = _ossClient.PutObject(aliConfig.BucketName, ossRelativePath, localFilePath);
 | ||
| 
 | ||
|         }
 | ||
|         else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
 | ||
|         {
 | ||
|             var minIOConfig = ObjectStoreServiceOptions.MinIO;
 | ||
| 
 | ||
| 
 | ||
|             var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
 | ||
|                 .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
 | ||
|                 .Build();
 | ||
| 
 | ||
|             var putObjectArgs = new PutObjectArgs()
 | ||
|                    .WithBucket(minIOConfig.BucketName)
 | ||
|                    .WithObject(ossRelativePath)
 | ||
|                    .WithFileName(localFilePath);
 | ||
| 
 | ||
|             await minioClient.PutObjectAsync(putObjectArgs);
 | ||
|         }
 | ||
|         else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
 | ||
|         {
 | ||
|             var awsConfig = ObjectStoreServiceOptions.AWS;
 | ||
| 
 | ||
|             // 提供awsAccessKeyId和awsSecretAccessKey构造凭证
 | ||
|             var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
 | ||
| 
 | ||
|             //提供awsEndPoint(域名)进行访问配置
 | ||
|             var clientConfig = new AmazonS3Config
 | ||
|             {
 | ||
|                 RegionEndpoint = RegionEndpoint.USEast1,
 | ||
|                 UseHttp = true,
 | ||
|             };
 | ||
| 
 | ||
|             var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
 | ||
| 
 | ||
|             var putObjectRequest = new Amazon.S3.Model.PutObjectRequest()
 | ||
|             {
 | ||
|                 BucketName = awsConfig.BucketName,
 | ||
|                 FilePath = localFilePath,
 | ||
|                 Key = ossRelativePath,
 | ||
|             };
 | ||
| 
 | ||
|             await amazonS3Client.PutObjectAsync(putObjectRequest);
 | ||
| 
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|             throw new BusinessValidationFailedException("未定义的存储介质类型");
 | ||
|         }
 | ||
|         return "/" + ossRelativePath;
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     public async Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath)
 | ||
|     {
 | ||
|         BackBatchGetToken();
 | ||
| 
 | ||
|         ossRelativePath = ossRelativePath.TrimStart('/');
 | ||
|         try
 | ||
|         {
 | ||
| 
 | ||
| 
 | ||
|             if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
 | ||
|             {
 | ||
|                 var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
 | ||
| 
 | ||
|                 var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
 | ||
| 
 | ||
|                 var result = _ossClient.GetObject(aliConfig.BucketName, ossRelativePath);
 | ||
| 
 | ||
|                 // 将下载的文件流保存到本地文件
 | ||
|                 using (var fs = File.OpenWrite(localFilePath))
 | ||
|                 {
 | ||
|                     await result.Content.CopyToAsync(fs);
 | ||
|                 }
 | ||
| 
 | ||
|             }
 | ||
|             else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
 | ||
|             {
 | ||
|                 var minIOConfig = ObjectStoreServiceOptions.MinIO;
 | ||
| 
 | ||
|                 var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
 | ||
|                     .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
 | ||
|                     .Build();
 | ||
| 
 | ||
|                 var getObjectArgs = new GetObjectArgs()
 | ||
|                 .WithBucket(minIOConfig.BucketName)
 | ||
|                 .WithObject(ossRelativePath)
 | ||
|                 .WithFile(localFilePath);
 | ||
| 
 | ||
|                 await minioClient.GetObjectAsync(getObjectArgs);
 | ||
| 
 | ||
|             }
 | ||
|             else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
 | ||
|             {
 | ||
|                 var awsConfig = ObjectStoreServiceOptions.AWS;
 | ||
| 
 | ||
|                 // 提供awsAccessKeyId和awsSecretAccessKey构造凭证
 | ||
|                 var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
 | ||
| 
 | ||
|                 //提供awsEndPoint(域名)进行访问配置
 | ||
|                 var clientConfig = new AmazonS3Config
 | ||
|                 {
 | ||
|                     RegionEndpoint = RegionEndpoint.USEast1,
 | ||
|                     UseHttp = true,
 | ||
|                 };
 | ||
| 
 | ||
|                 var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
 | ||
| 
 | ||
|                 var getObjectArgs = new Amazon.S3.Model.GetObjectRequest()
 | ||
|                 {
 | ||
|                     BucketName = awsConfig.BucketName,
 | ||
|                     Key = ossRelativePath,
 | ||
|                 };
 | ||
| 
 | ||
| 
 | ||
|                 await (await amazonS3Client.GetObjectAsync(getObjectArgs)).WriteResponseStreamToFileAsync(localFilePath, true, CancellationToken.None);
 | ||
| 
 | ||
| 
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 throw new BusinessValidationFailedException("未定义的存储介质类型");
 | ||
|             }
 | ||
|         }
 | ||
|         catch (Exception ex)
 | ||
|         {
 | ||
| 
 | ||
|             throw new BusinessValidationFailedException("oss下载失败!" + ex.Message);
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
|     public async Task<Stream> GetStreamFromOSSAsync(string ossRelativePath)
 | ||
|     {
 | ||
|         BackBatchGetToken();
 | ||
|         ossRelativePath = ossRelativePath.TrimStart('/');
 | ||
| 
 | ||
|         try
 | ||
|         {
 | ||
|             if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
 | ||
|             {
 | ||
|                 var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
 | ||
| 
 | ||
|                 var _ossClient = new OssClient(
 | ||
|                     RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint,
 | ||
|                     AliyunOSSTempToken.AccessKeyId,
 | ||
|                     AliyunOSSTempToken.AccessKeySecret,
 | ||
|                     AliyunOSSTempToken.SecurityToken
 | ||
|                 );
 | ||
| 
 | ||
|                 var result = _ossClient.GetObject(aliConfig.BucketName, ossRelativePath);
 | ||
| 
 | ||
|                 // 将OSS返回的流复制到内存流中并返回
 | ||
|                 var memoryStream = new MemoryStream();
 | ||
|                 await result.Content.CopyToAsync(memoryStream);
 | ||
|                 memoryStream.Position = 0; // 重置位置以便读取
 | ||
|                 return memoryStream;
 | ||
|             }
 | ||
|             else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
 | ||
|             {
 | ||
|                 var minIOConfig = ObjectStoreServiceOptions.MinIO;
 | ||
| 
 | ||
|                 var minioClient = new MinioClient()
 | ||
|                     .WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
 | ||
|                     .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey)
 | ||
|                     .WithSSL(minIOConfig.UseSSL)
 | ||
|                     .Build();
 | ||
| 
 | ||
|                 var memoryStream = new MemoryStream();
 | ||
| 
 | ||
|                 var getObjectArgs = new GetObjectArgs()
 | ||
|                     .WithBucket(minIOConfig.BucketName)
 | ||
|                     .WithObject(ossRelativePath)
 | ||
|                     .WithCallbackStream(stream => stream.CopyToAsync(memoryStream));
 | ||
| 
 | ||
|                 await minioClient.GetObjectAsync(getObjectArgs);
 | ||
|                 memoryStream.Position = 0;
 | ||
|                 return memoryStream;
 | ||
|             }
 | ||
|             else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
 | ||
|             {
 | ||
|                 var awsConfig = ObjectStoreServiceOptions.AWS;
 | ||
| 
 | ||
|                 var credentials = new SessionAWSCredentials(
 | ||
|                     AWSTempToken.AccessKeyId,
 | ||
|                     AWSTempToken.SecretAccessKey,
 | ||
|                     AWSTempToken.SessionToken
 | ||
|                 );
 | ||
| 
 | ||
|                 var clientConfig = new AmazonS3Config
 | ||
|                 {
 | ||
|                     RegionEndpoint = RegionEndpoint.USEast1,
 | ||
|                     UseHttp = true,
 | ||
|                 };
 | ||
| 
 | ||
|                 var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
 | ||
| 
 | ||
|                 var getObjectRequest = new Amazon.S3.Model.GetObjectRequest
 | ||
|                 {
 | ||
|                     BucketName = awsConfig.BucketName,
 | ||
|                     Key = ossRelativePath
 | ||
|                 };
 | ||
| 
 | ||
|                 var response = await amazonS3Client.GetObjectAsync(getObjectRequest);
 | ||
| 
 | ||
|                 var memoryStream = new MemoryStream();
 | ||
|                 await response.ResponseStream.CopyToAsync(memoryStream);
 | ||
|                 memoryStream.Position = 0;
 | ||
|                 return memoryStream;
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 throw new BusinessValidationFailedException("未定义的存储介质类型");
 | ||
|             }
 | ||
|         }
 | ||
|         catch (Exception ex)
 | ||
|         {
 | ||
|             throw new BusinessValidationFailedException("oss流获取失败! " + ex.Message);
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     public async Task<string> GetSignedUrl(string ossRelativePath)
 | ||
|     {
 | ||
|         GetObjectStoreTempToken();
 | ||
| 
 | ||
|         ossRelativePath = ossRelativePath.TrimStart('/');
 | ||
|         try
 | ||
|         {
 | ||
| 
 | ||
| 
 | ||
|             if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
 | ||
|             {
 | ||
|                 var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
 | ||
| 
 | ||
|                 var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
 | ||
| 
 | ||
|                 // 生成签名URL。
 | ||
|                 var req = new GeneratePresignedUriRequest(aliConfig.BucketName, ossRelativePath, SignHttpMethod.Get)
 | ||
|                 {
 | ||
|                     // 设置签名URL过期时间,默认值为3600秒。
 | ||
|                     Expiration = DateTime.Now.AddHours(1),
 | ||
|                 };
 | ||
|                 var uri = _ossClient.GeneratePresignedUri(req);
 | ||
| 
 | ||
|                 return uri.PathAndQuery;
 | ||
| 
 | ||
|             }
 | ||
|             else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
 | ||
|             {
 | ||
|                 var minIOConfig = ObjectStoreServiceOptions.MinIO;
 | ||
| 
 | ||
|                 var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
 | ||
|                     .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
 | ||
|                     .Build();
 | ||
| 
 | ||
| 
 | ||
|                 var args = new PresignedGetObjectArgs()
 | ||
|                     .WithBucket(minIOConfig.BucketName)
 | ||
|                     .WithObject(ossRelativePath)
 | ||
|                     .WithExpiry(3600)
 | ||
|                     /*.WithHeaders(reqParams)*/;
 | ||
| 
 | ||
|                 var presignedUrl = await minioClient.PresignedGetObjectAsync(args);
 | ||
| 
 | ||
|                 Uri uri = new Uri(presignedUrl);
 | ||
| 
 | ||
|                 string relativePath = uri.PathAndQuery;
 | ||
| 
 | ||
| 
 | ||
|                 return relativePath;
 | ||
| 
 | ||
|             }
 | ||
|             else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
 | ||
|             {
 | ||
|                 var awsConfig = ObjectStoreServiceOptions.AWS;
 | ||
| 
 | ||
| 
 | ||
|                 // 提供awsAccessKeyId和awsSecretAccessKey构造凭证
 | ||
|                 var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
 | ||
| 
 | ||
|                 //提供awsEndPoint(域名)进行访问配置
 | ||
|                 var clientConfig = new AmazonS3Config
 | ||
|                 {
 | ||
|                     RegionEndpoint = RegionEndpoint.USEast1,
 | ||
|                     UseHttp = true,
 | ||
|                 };
 | ||
| 
 | ||
|                 var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
 | ||
| 
 | ||
|                 var presignedUrl = await amazonS3Client.GetPreSignedURLAsync(new GetPreSignedUrlRequest()
 | ||
|                 {
 | ||
|                     BucketName = awsConfig.BucketName,
 | ||
|                     Key = ossRelativePath,
 | ||
|                     Expires = DateTime.UtcNow.AddMinutes(120)
 | ||
|                 });
 | ||
| 
 | ||
|                 Uri uri = new Uri(presignedUrl);
 | ||
| 
 | ||
|                 string relativePath = uri.PathAndQuery;
 | ||
| 
 | ||
| 
 | ||
|                 return relativePath;
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 throw new BusinessValidationFailedException("未定义的存储介质类型");
 | ||
|             }
 | ||
|         }
 | ||
|         catch (Exception ex)
 | ||
|         {
 | ||
| 
 | ||
|             throw new BusinessValidationFailedException("oss授权url失败!" + ex.Message);
 | ||
|         }
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     /// <summary>
 | ||
|     /// 移动OSS文件到新路径
 | ||
|     /// </summary>
 | ||
|     /// <param name="sourcePath">原文件路径(格式:bucket/key)</param>
 | ||
|     /// <param name="destPath">新文件路径(格式:bucket/key)</param>
 | ||
|     /// <param name="overwrite">是否覆盖已存在的目标文件(默认true)</param>
 | ||
|     public async Task MoveObject(string sourcePath, string destPath, bool overwrite = true)
 | ||
|     {
 | ||
|         GetObjectStoreTempToken();
 | ||
| 
 | ||
|         switch (ObjectStoreServiceOptions.ObjectStoreUse)
 | ||
|         {
 | ||
|             case "AliyunOSS":
 | ||
|                 #region 阿里云
 | ||
|                 var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
 | ||
|                 var client = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
 | ||
|                 if (sourcePath.StartsWith("/"))
 | ||
|                 {
 | ||
|                     sourcePath = sourcePath.Substring(1);
 | ||
|                 }
 | ||
| 
 | ||
| 
 | ||
|                 if (destPath.StartsWith("/"))
 | ||
|                 {
 | ||
|                     destPath = destPath.Substring(1);
 | ||
|                 }
 | ||
| 
 | ||
|                 var sourceBucket = aliConfig.BucketName;
 | ||
|                 var sourceKey = sourcePath;
 | ||
| 
 | ||
|                 var destBucket = aliConfig.BucketName;
 | ||
| 
 | ||
|                 var destKey = destPath;
 | ||
| 
 | ||
| 
 | ||
|                 try
 | ||
|                 {
 | ||
|                     // 检查目标是否存在(当不允许覆盖时)
 | ||
|                     if (!overwrite && client.DoesObjectExist(destBucket, destKey))
 | ||
|                     {
 | ||
|                         throw new InvalidOperationException("File Exist");
 | ||
|                     }
 | ||
| 
 | ||
| 
 | ||
|                     //var copyRequest = new Aliyun.OSS.CopyObjectRequest(sourceBucket, sourceKey, sourceBucket, destKey);
 | ||
|                     //var result = client.CopyObject(copyRequest);
 | ||
| 
 | ||
|                     //// 2. 删除原文件(可选,根据是否需要保留原文件)
 | ||
|                     //client.DeleteObject(sourceBucket, sourceKey);
 | ||
| 
 | ||
|                     // 执行复制
 | ||
|                     var copyRequestAli = new Aliyun.OSS.CopyObjectRequest(
 | ||
|                         sourceBucket, sourceKey,
 | ||
|                         destBucket, destKey);
 | ||
| 
 | ||
|                     // 保持原文件元数据
 | ||
|                     copyRequestAli.NewObjectMetadata = new ObjectMetadata
 | ||
|                     {
 | ||
|                         ContentType = client.GetObjectMetadata(sourceBucket, sourceKey).ContentType
 | ||
|                     };
 | ||
| 
 | ||
|                     var result = client.CopyObject(copyRequestAli);
 | ||
| 
 | ||
|                     // 删除原文件(仅在复制成功后)
 | ||
|                     client.DeleteObject(sourceBucket, sourceKey);
 | ||
|                 }
 | ||
|                 catch (OssException ex)
 | ||
|                 {
 | ||
|                     throw new Exception($"[{ex.ErrorCode}] {ex.Message}", ex);
 | ||
|                 }
 | ||
|                 #endregion
 | ||
| 
 | ||
|                 break;
 | ||
|             case "MinIO":
 | ||
|                 #region MinIO
 | ||
|                 var minIOConfig = ObjectStoreServiceOptions.MinIO;
 | ||
|                 var minioClient = new MinioClient()
 | ||
|                  .WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
 | ||
|                  .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey)
 | ||
|                  .WithSSL(minIOConfig.UseSSL)
 | ||
|                  .Build();
 | ||
| 
 | ||
|                 // 定义源路径和目标路径
 | ||
|                 string destinationKey = "b路径/文件名";
 | ||
| 
 | ||
|                 try
 | ||
|                 {
 | ||
|                     // 1. 复制文件到新路径[2,5](@ref)
 | ||
|                     using (var memoryStream = new MemoryStream())
 | ||
|                     {
 | ||
|                         // 下载源文件流
 | ||
|                         await minioClient.GetObjectAsync(new GetObjectArgs()
 | ||
|                             .WithBucket(minIOConfig.BucketName)
 | ||
|                             .WithObject(sourcePath)
 | ||
|                             .WithCallbackStream(stream => stream.CopyTo(memoryStream)));
 | ||
| 
 | ||
|                         memoryStream.Position = 0; // 重置流位置
 | ||
| 
 | ||
|                         // 上传到新路径
 | ||
|                         await minioClient.PutObjectAsync(new PutObjectArgs()
 | ||
|                             .WithBucket(minIOConfig.BucketName)
 | ||
|                             .WithObject(destinationKey)
 | ||
|                             .WithStreamData(memoryStream)
 | ||
|                             .WithObjectSize(memoryStream.Length));
 | ||
|                     }
 | ||
| 
 | ||
|                     // 2. 删除原文件[1,6](@ref)
 | ||
|                     await minioClient.RemoveObjectAsync(new RemoveObjectArgs()
 | ||
|                         .WithBucket(minIOConfig.BucketName)
 | ||
|                         .WithObject(sourcePath));
 | ||
|                 }
 | ||
|                 catch (MinioException ex)
 | ||
|                 {
 | ||
|                     // 处理异常(例如:记录日志或抛出)
 | ||
|                     throw new Exception();
 | ||
|                 }
 | ||
|                 #endregion
 | ||
| 
 | ||
|                 break;
 | ||
|             case "AWS":
 | ||
|                 #region AWS
 | ||
|                 var awsConfig = ObjectStoreServiceOptions.AWS;
 | ||
| 
 | ||
|                 var credentials = new SessionAWSCredentials(
 | ||
|                     AWSTempToken.AccessKeyId,
 | ||
|                     AWSTempToken.SecretAccessKey,
 | ||
|                     AWSTempToken.SessionToken
 | ||
|                 );
 | ||
| 
 | ||
|                 var clientConfig = new AmazonS3Config
 | ||
|                 {
 | ||
|                     RegionEndpoint = RegionEndpoint.USEast1,
 | ||
|                     UseHttp = true,
 | ||
|                 };
 | ||
| 
 | ||
|                 var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
 | ||
| 
 | ||
|                 // 定义原路径和目标路径
 | ||
| 
 | ||
| 
 | ||
|                 // 1. 复制对象到新路径
 | ||
|                 var copyRequest = new Amazon.S3.Model.CopyObjectRequest
 | ||
|                 {
 | ||
|                     SourceBucket = awsConfig.BucketName,
 | ||
|                     SourceKey = sourcePath,
 | ||
|                     DestinationBucket = awsConfig.BucketName,
 | ||
|                     DestinationKey = destPath
 | ||
|                 };
 | ||
| 
 | ||
|                 try
 | ||
|                 {
 | ||
|                     // 执行复制操作
 | ||
|                     await amazonS3Client.CopyObjectAsync(copyRequest);
 | ||
| 
 | ||
|                     // 2. 删除原对象
 | ||
|                     var deleteRequest = new Amazon.S3.Model.DeleteObjectRequest
 | ||
|                     {
 | ||
|                         BucketName = awsConfig.BucketName,
 | ||
|                         Key = sourcePath
 | ||
|                     };
 | ||
|                     await amazonS3Client.DeleteObjectAsync(deleteRequest);
 | ||
| 
 | ||
| 
 | ||
|                 }
 | ||
|                 catch (AmazonS3Exception ex)
 | ||
|                 {
 | ||
|                     Console.WriteLine($"ERROR: {ex.Message}");
 | ||
|                     // 可根据异常类型细化处理(如文件不存在、权限问题等)
 | ||
|                 }
 | ||
|                 #endregion
 | ||
|                 break;
 | ||
|             default:
 | ||
|                 throw new BusinessValidationFailedException("ERROR");
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
|     /// <summary>
 | ||
|     /// 获取所有根目录名称
 | ||
|     /// </summary>
 | ||
|     /// <returns></returns>
 | ||
|     public List<string> GetRootFolderNames()
 | ||
|     {
 | ||
|         GetObjectStoreTempToken();
 | ||
|         var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
 | ||
|         var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint,
 | ||
|                                         AliyunOSSTempToken.AccessKeyId,
 | ||
|                                         AliyunOSSTempToken.AccessKeySecret,
 | ||
|                                         AliyunOSSTempToken.SecurityToken);
 | ||
| 
 | ||
|         List<string> rootFolders = new List<string>();
 | ||
|         string nextMarker = null;
 | ||
| 
 | ||
|         try
 | ||
|         {
 | ||
|             ObjectListing objectListing = null;
 | ||
|             do
 | ||
|             {
 | ||
|                 // 列出根目录下的对象和文件夹
 | ||
|                 objectListing = _ossClient.ListObjects(new Aliyun.OSS.ListObjectsRequest(aliConfig.BucketName)
 | ||
|                 {
 | ||
| 
 | ||
|                     MaxKeys = 1000,
 | ||
|                     Marker = nextMarker,
 | ||
|                     Delimiter = "/"  // 使用分隔符来模拟文件夹
 | ||
|                 });
 | ||
| 
 | ||
|                 // 遍历 CommonPrefixes 获取根文件夹名称
 | ||
|                 foreach (var prefix in objectListing.CommonPrefixes)
 | ||
|                 {
 | ||
|                     rootFolders.Add(prefix.TrimEnd('/')); // 去掉末尾的斜杠
 | ||
|                 }
 | ||
| 
 | ||
|                 // 设置 NextMarker 以获取下一页的数据
 | ||
|                 nextMarker = objectListing.NextMarker;
 | ||
| 
 | ||
|             } while (objectListing.IsTruncated);
 | ||
|         }
 | ||
|         catch (Exception ex)
 | ||
|         {
 | ||
|             Console.WriteLine($"Error: {ex.Message}");
 | ||
|         }
 | ||
| 
 | ||
|         return rootFolders;
 | ||
|     }
 | ||
| 
 | ||
|     /// <summary>
 | ||
|     /// 删除某个目录的文件
 | ||
|     /// </summary>
 | ||
|     /// <param name="prefix"></param>
 | ||
|     /// <returns></returns>
 | ||
|     public async Task DeleteFromPrefix(string prefix, bool isCache = false)
 | ||
|     {
 | ||
|         GetObjectStoreTempToken();
 | ||
| 
 | ||
|         if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
 | ||
|         {
 | ||
|             var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
 | ||
| 
 | ||
|             var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
 | ||
| 
 | ||
|             var bucketName = string.Empty;
 | ||
| 
 | ||
|             if (isCache)
 | ||
|             {
 | ||
|                 Uri uri = new Uri(aliConfig.ViewEndpoint);
 | ||
|                 string host = uri.Host; // 获取 "zy-irc-test-dev-cache.oss-cn-shanghai.aliyuncs.com"
 | ||
|                 string[] parts = host.Split('.');
 | ||
|                 bucketName = parts[0];
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 bucketName = aliConfig.BucketName;
 | ||
|             }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|             try
 | ||
|             {
 | ||
|                 ObjectListing objectListing = null;
 | ||
|                 string nextMarker = null;
 | ||
|                 do
 | ||
|                 {
 | ||
|                     // 使用 prefix 模拟目录结构,设置 MaxKeys 和 NextMarker
 | ||
|                     objectListing = _ossClient.ListObjects(new Aliyun.OSS.ListObjectsRequest(bucketName)
 | ||
|                     {
 | ||
|                         Prefix = prefix,
 | ||
|                         MaxKeys = 1000,
 | ||
|                         Marker = nextMarker
 | ||
|                     });
 | ||
| 
 | ||
|                     List<string> keys = objectListing.ObjectSummaries.Select(t => t.Key).ToList();
 | ||
| 
 | ||
|                     // 删除获取到的文件
 | ||
|                     if (keys.Count > 0)
 | ||
|                     {
 | ||
|                         _ossClient.DeleteObjects(new Aliyun.OSS.DeleteObjectsRequest(bucketName, keys, false));
 | ||
|                     }
 | ||
| 
 | ||
|                     // 设置 NextMarker 以获取下一页的数据
 | ||
|                     nextMarker = objectListing.NextMarker;
 | ||
| 
 | ||
|                 } while (objectListing.IsTruncated);
 | ||
|             }
 | ||
|             catch (Exception ex)
 | ||
|             {
 | ||
|                 Console.WriteLine($"Error: {ex.Message}");
 | ||
|             }
 | ||
| 
 | ||
| 
 | ||
|         }
 | ||
|         else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
 | ||
|         {
 | ||
|             var minIOConfig = ObjectStoreServiceOptions.MinIO;
 | ||
| 
 | ||
| 
 | ||
|             var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
 | ||
|                 .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
 | ||
|                 .Build();
 | ||
| 
 | ||
| 
 | ||
|             var listArgs = new ListObjectsArgs().WithBucket(minIOConfig.BucketName).WithPrefix(prefix).WithRecursive(true);
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|             // 创建一个空列表用于存储对象键
 | ||
|             var objects = new List<string>();
 | ||
| 
 | ||
|             // 使用 await foreach 来异步迭代对象列表
 | ||
|             await foreach (var item in minioClient.ListObjectsEnumAsync(listArgs))
 | ||
|             {
 | ||
|                 objects.Add(item.Key);
 | ||
|             }
 | ||
| 
 | ||
| 
 | ||
|             if (objects.Count > 0)
 | ||
|             {
 | ||
|                 var objArgs = new RemoveObjectsArgs()
 | ||
|               .WithBucket(minIOConfig.BucketName)
 | ||
|               .WithObjects(objects);
 | ||
| 
 | ||
|                 // 删除对象
 | ||
|                 await minioClient.RemoveObjectsAsync(objArgs);
 | ||
|             }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         }
 | ||
|         else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
 | ||
|         {
 | ||
| 
 | ||
|             var awsConfig = ObjectStoreServiceOptions.AWS;
 | ||
| 
 | ||
|             // 提供awsAccessKeyId和awsSecretAccessKey构造凭证
 | ||
|             var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
 | ||
| 
 | ||
|             //提供awsEndPoint(域名)进行访问配置
 | ||
|             var clientConfig = new AmazonS3Config
 | ||
|             {
 | ||
|                 RegionEndpoint = RegionEndpoint.USEast1,
 | ||
|                 UseHttp = true,
 | ||
|             };
 | ||
| 
 | ||
|             var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
 | ||
| 
 | ||
|             // 列出指定前缀下的所有对象
 | ||
|             var listObjectsRequest = new ListObjectsV2Request
 | ||
|             {
 | ||
|                 BucketName = awsConfig.BucketName,
 | ||
|                 Prefix = prefix
 | ||
|             };
 | ||
| 
 | ||
|             var listObjectsResponse = await amazonS3Client.ListObjectsV2Async(listObjectsRequest);
 | ||
| 
 | ||
|             if (listObjectsResponse.S3Objects.Count > 0)
 | ||
|             {
 | ||
|                 // 准备删除请求
 | ||
|                 var deleteObjectsRequest = new Amazon.S3.Model.DeleteObjectsRequest
 | ||
|                 {
 | ||
|                     BucketName = awsConfig.BucketName,
 | ||
|                     Objects = new List<KeyVersion>()
 | ||
|                 };
 | ||
| 
 | ||
|                 foreach (var s3Object in listObjectsResponse.S3Objects)
 | ||
|                 {
 | ||
|                     deleteObjectsRequest.Objects.Add(new KeyVersion
 | ||
|                     {
 | ||
|                         Key = s3Object.Key
 | ||
|                     });
 | ||
|                 }
 | ||
| 
 | ||
|                 // 批量删除对象
 | ||
|                 var deleteObjectsResponse = await amazonS3Client.DeleteObjectsAsync(deleteObjectsRequest);
 | ||
|             }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|             throw new BusinessValidationFailedException("未定义的存储介质类型");
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     public async Task DeleteObjects(List<string> objectKeys)
 | ||
|     {
 | ||
|         GetObjectStoreTempToken();
 | ||
| 
 | ||
|         if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
 | ||
|         {
 | ||
|             var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
 | ||
| 
 | ||
|             var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
 | ||
| 
 | ||
|             if (objectKeys.Count > 0)
 | ||
|             {
 | ||
|                 var result = _ossClient.DeleteObjects(new Aliyun.OSS.DeleteObjectsRequest(aliConfig.BucketName, objectKeys, false));
 | ||
| 
 | ||
|             }
 | ||
|         }
 | ||
|         else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
 | ||
|         {
 | ||
|             var minIOConfig = ObjectStoreServiceOptions.MinIO;
 | ||
| 
 | ||
| 
 | ||
|             var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
 | ||
|                 .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
 | ||
|             .Build();
 | ||
| 
 | ||
| 
 | ||
|             if (objectKeys.Count > 0)
 | ||
|             {
 | ||
|                 var objArgs = new RemoveObjectsArgs()
 | ||
|               .WithBucket(minIOConfig.BucketName)
 | ||
|               .WithObjects(objectKeys);
 | ||
| 
 | ||
|                 // 删除对象
 | ||
|                 await minioClient.RemoveObjectsAsync(objArgs);
 | ||
|             }
 | ||
|         }
 | ||
|         else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
 | ||
|         {
 | ||
| 
 | ||
|             var awsConfig = ObjectStoreServiceOptions.AWS;
 | ||
| 
 | ||
| 
 | ||
|             // 提供awsAccessKeyId和awsSecretAccessKey构造凭证
 | ||
|             var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
 | ||
| 
 | ||
|             //提供awsEndPoint(域名)进行访问配置
 | ||
|             var clientConfig = new AmazonS3Config
 | ||
|             {
 | ||
|                 RegionEndpoint = RegionEndpoint.USEast1,
 | ||
|                 UseHttp = true,
 | ||
|             };
 | ||
| 
 | ||
|             var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
 | ||
| 
 | ||
|             if (objectKeys.Count > 0)
 | ||
|             {
 | ||
|                 // 准备删除请求
 | ||
|                 var deleteObjectsRequest = new Amazon.S3.Model.DeleteObjectsRequest
 | ||
|                 {
 | ||
|                     BucketName = awsConfig.BucketName,
 | ||
|                     Objects = objectKeys.Select(t => new KeyVersion() { Key = t }).ToList()
 | ||
|                 };
 | ||
| 
 | ||
| 
 | ||
|                 // 批量删除对象
 | ||
|                 var deleteObjectsResponse = await amazonS3Client.DeleteObjectsAsync(deleteObjectsRequest);
 | ||
|             }
 | ||
| 
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|             throw new BusinessValidationFailedException("未定义的存储介质类型");
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     public async Task<long> GetObjectSizeAsync(string sourcePath)
 | ||
|     {
 | ||
|         BackBatchGetToken();
 | ||
| 
 | ||
| 
 | ||
|         var objectkey = sourcePath.Trim('/');
 | ||
| 
 | ||
|         if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
 | ||
|         {
 | ||
|             var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
 | ||
| 
 | ||
|             var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
 | ||
| 
 | ||
|             var key = HttpUtility.UrlDecode(objectkey);
 | ||
|             var metadata = _ossClient.GetObjectMetadata(aliConfig.BucketName, key);
 | ||
| 
 | ||
|             long fileSize = metadata?.ContentLength ?? 0; // 文件大小(字节)
 | ||
| 
 | ||
|             return fileSize;
 | ||
|         }
 | ||
|         else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
 | ||
|         {
 | ||
|             var minIOConfig = ObjectStoreServiceOptions.MinIO;
 | ||
| 
 | ||
| 
 | ||
|             var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
 | ||
|                 .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
 | ||
|             .Build();
 | ||
| 
 | ||
| 
 | ||
|             var stat = await minioClient.StatObjectAsync(new Minio.DataModel.Args.StatObjectArgs()
 | ||
|                  .WithBucket(minIOConfig.BucketName)
 | ||
|                  .WithObject(objectkey));
 | ||
| 
 | ||
|             return stat.Size; // 文件大小(字节)
 | ||
|         }
 | ||
|         else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
 | ||
|         {
 | ||
| 
 | ||
|             var awsConfig = ObjectStoreServiceOptions.AWS;
 | ||
| 
 | ||
| 
 | ||
|             // 提供awsAccessKeyId和awsSecretAccessKey构造凭证
 | ||
|             var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
 | ||
| 
 | ||
|             //提供awsEndPoint(域名)进行访问配置
 | ||
|             var clientConfig = new AmazonS3Config
 | ||
|             {
 | ||
|                 RegionEndpoint = RegionEndpoint.USEast1,
 | ||
|                 UseHttp = true,
 | ||
|             };
 | ||
| 
 | ||
|             var request = new Amazon.S3.Model.GetObjectMetadataRequest
 | ||
|             {
 | ||
|                 BucketName = awsConfig.BucketName,
 | ||
|                 Key = objectkey
 | ||
|             };
 | ||
| 
 | ||
|             var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
 | ||
| 
 | ||
|             var response = await amazonS3Client.GetObjectMetadataAsync(request);
 | ||
| 
 | ||
|             long fileSize = response.ContentLength; // 文件大小(字节)
 | ||
| 
 | ||
|             return fileSize;
 | ||
| 
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|             throw new BusinessValidationFailedException("未定义的存储介质类型");
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|     public ObjectStoreDTO GetObjectStoreTempToken()
 | ||
|     {
 | ||
| 
 | ||
|         var ossOptions = ObjectStoreServiceOptions.AliyunOSS;
 | ||
| 
 | ||
|         if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
 | ||
|         {
 | ||
|             var client = new Client(new AlibabaCloud.OpenApiClient.Models.Config()
 | ||
|             {
 | ||
|                 AccessKeyId = ossOptions.AccessKeyId,
 | ||
|                 AccessKeySecret = ossOptions.AccessKeySecret,
 | ||
|                 //AccessKeyId = "LTAI5tJV76pYX5yPg1N9QVE8",
 | ||
|                 //AccessKeySecret = "roRNLa9YG1of4pYruJGCNKBXEWTAWa",
 | ||
| 
 | ||
|                 Endpoint = "sts.cn-hangzhou.aliyuncs.com"
 | ||
|             });
 | ||
| 
 | ||
|             var assumeRoleRequest = new AlibabaCloud.SDK.Sts20150401.Models.AssumeRoleRequest();
 | ||
|             // 将<YOUR_ROLE_SESSION_NAME>设置为自定义的会话名称,例如oss-role-session。
 | ||
|             assumeRoleRequest.RoleSessionName = $"session-name-{NewId.NextGuid()}";
 | ||
|             // 将<YOUR_ROLE_ARN>替换为拥有上传文件到指定OSS Bucket权限的RAM角色的ARN。
 | ||
|             assumeRoleRequest.RoleArn = ossOptions.RoleArn;
 | ||
|             //assumeRoleRequest.RoleArn = "acs:ram::1899121822495495:role/webdirect";
 | ||
|             assumeRoleRequest.DurationSeconds = ossOptions.DurationSeconds;
 | ||
|             var runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();
 | ||
|             var response = client.AssumeRoleWithOptions(assumeRoleRequest, runtime);
 | ||
|             var credentials = response.Body.Credentials;
 | ||
| 
 | ||
|             var tempToken = new AliyunOSSTempToken()
 | ||
|             {
 | ||
|                 AccessKeyId = credentials.AccessKeyId,
 | ||
|                 AccessKeySecret = credentials.AccessKeySecret,
 | ||
| 
 | ||
|                 //转为服务器时区,最后统一转为客户端时区
 | ||
|                 Expiration = TimeZoneInfo.ConvertTimeFromUtc(DateTime.Parse(credentials.Expiration), TimeZoneInfo.Local),
 | ||
|                 SecurityToken = credentials.SecurityToken,
 | ||
| 
 | ||
| 
 | ||
|                 Region = ossOptions.Region,
 | ||
|                 BucketName = ossOptions.BucketName,
 | ||
|                 EndPoint = ossOptions.EndPoint,
 | ||
|                 ViewEndpoint = ossOptions.ViewEndpoint,
 | ||
|                 PreviewEndpoint = ossOptions.PreviewEndpoint
 | ||
| 
 | ||
|             };
 | ||
| 
 | ||
|             AliyunOSSTempToken = tempToken;
 | ||
| 
 | ||
|             return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, AliyunOSS = tempToken };
 | ||
|         }
 | ||
|         else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
 | ||
|         {
 | ||
|             return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, MinIO = ObjectStoreServiceOptions.MinIO };
 | ||
|         }
 | ||
|         else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
 | ||
|         {
 | ||
|             var awsOptions = ObjectStoreServiceOptions.AWS;
 | ||
| 
 | ||
|             //aws 临时凭证
 | ||
|             // 创建 STS 客户端
 | ||
|             var stsClient = new AmazonSecurityTokenServiceClient(awsOptions.AccessKeyId, awsOptions.SecretAccessKey);
 | ||
| 
 | ||
|             // 使用 AssumeRole 请求临时凭证
 | ||
|             var assumeRoleRequest = new AssumeRoleRequest
 | ||
|             {
 | ||
| 
 | ||
|                 RoleArn = awsOptions.RoleArn, // 角色 ARN
 | ||
|                 RoleSessionName = $"session-name-{NewId.NextGuid()}",
 | ||
|                 DurationSeconds = awsOptions.DurationSeconds          // 临时凭证有效期
 | ||
|             };
 | ||
| 
 | ||
|             var assumeRoleResponse = stsClient.AssumeRoleAsync(assumeRoleRequest).Result;
 | ||
| 
 | ||
|             var credentials = assumeRoleResponse.Credentials;
 | ||
| 
 | ||
|             var tempToken = new AWSTempToken()
 | ||
|             {
 | ||
|                 AccessKeyId = credentials.AccessKeyId,
 | ||
|                 SecretAccessKey = credentials.SecretAccessKey,
 | ||
|                 SessionToken = credentials.SessionToken,
 | ||
|                 Expiration = credentials.Expiration,
 | ||
|                 Region = awsOptions.Region,
 | ||
|                 BucketName = awsOptions.BucketName,
 | ||
|                 EndPoint = awsOptions.EndPoint,
 | ||
|                 ViewEndpoint = awsOptions.ViewEndpoint,
 | ||
| 
 | ||
|             };
 | ||
| 
 | ||
|             AWSTempToken = tempToken;
 | ||
|             return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, AWS = tempToken };
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|             throw new BusinessValidationFailedException("未定义的存储介质类型");
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
| }
 |