diff --git a/IRaCIS.Core.Application/Helper/OSSService.cs b/IRaCIS.Core.Application/Helper/OSSService.cs index b82dda499..88d3c86e5 100644 --- a/IRaCIS.Core.Application/Helper/OSSService.cs +++ b/IRaCIS.Core.Application/Helper/OSSService.cs @@ -15,6 +15,7 @@ using Microsoft.Extensions.Options; using Minio; using Minio.DataModel; using Minio.DataModel.Args; +using Minio.Exceptions; using System.Reactive.Linq; using System.Runtime.InteropServices; @@ -155,7 +156,7 @@ public interface IOSSService public ObjectStoreDTO GetObjectStoreTempToken(); - public void MoveObject(string sourcePath, string destPath, bool overwrite = true); + public Task MoveObject(string sourcePath, string destPath, bool overwrite = true); } @@ -543,68 +544,176 @@ public class OSSService : IOSSService /// 原文件路径(格式:bucket/key) /// 新文件路径(格式:bucket/key) /// 是否覆盖已存在的目标文件(默认true) - public void MoveObject(string sourcePath, string destPath, bool overwrite = true) + public async Task MoveObject(string sourcePath, string destPath, bool overwrite = true) { GetObjectStoreTempToken(); - var aliConfig = ObjectStoreServiceOptions.AliyunOSS; - var client = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken); + 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 copyRequest = new Aliyun.OSS.CopyObjectRequest( + sourceBucket, sourceKey, + destBucket, destKey); + + // 保持原文件元数据 + copyRequest.NewObjectMetadata = new ObjectMetadata + { + ContentType = client.GetObjectMetadata(sourceBucket, sourceKey).ContentType + }; + + var result = client.CopyObject(copyRequest); + + // 删除原文件(仅在复制成功后) + 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"); + + } - 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 copyRequest = new Aliyun.OSS.CopyObjectRequest( - sourceBucket, sourceKey, - destBucket, destKey); - - // 保持原文件元数据 - copyRequest.NewObjectMetadata = new ObjectMetadata - { - ContentType = client.GetObjectMetadata(sourceBucket, sourceKey).ContentType - }; - - var result = client.CopyObject(copyRequest); - - // 删除原文件(仅在复制成功后) - client.DeleteObject(sourceBucket, sourceKey); - } - catch (OssException ex) - { - throw new Exception($"[{ex.ErrorCode}] {ex.Message}", ex); - } } /// @@ -763,7 +872,6 @@ public class OSSService : IOSSService var awsConfig = ObjectStoreServiceOptions.AWS; - // 提供awsAccessKeyId和awsSecretAccessKey构造凭证 var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken); diff --git a/IRaCIS.Core.Application/Service/Doctor/AttachmentService.cs b/IRaCIS.Core.Application/Service/Doctor/AttachmentService.cs index 3f8f19061..06b7f0edc 100644 --- a/IRaCIS.Core.Application/Service/Doctor/AttachmentService.cs +++ b/IRaCIS.Core.Application/Service/Doctor/AttachmentService.cs @@ -222,7 +222,7 @@ namespace IRaCIS.Core.Application.Service attachment.Path = $"/systemData/reviewe/{attachment.Type}/{attachment.DoctorId}/{fileName}"; - _oSSService.MoveObject(attachmentData.Path, attachment.Path); + await _oSSService.MoveObject(attachmentData.Path, attachment.Path); }