From 8eb31d0c816bf110c051cb538bb80e45c375179f Mon Sep 17 00:00:00 2001 From: hang <872297557@qq.com> Date: Wed, 7 Jan 2026 16:41:56 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=A1=B9=E7=9B=AE=E5=81=9C?= =?UTF-8?q?=E6=AD=A2=EF=BC=8C=E5=BD=92=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IRaCIS.Core.Application/Helper/OSSService.cs | 670 ++++++++++++++---- .../IRaCIS.Core.Application.xml | 15 +- .../TrialSiteUser/TrialConfigService.cs | 33 +- IRaCIS.Core.Application/TestService.cs | 2 +- 4 files changed, 567 insertions(+), 153 deletions(-) diff --git a/IRaCIS.Core.Application/Helper/OSSService.cs b/IRaCIS.Core.Application/Helper/OSSService.cs index af6a95223..b272d5a82 100644 --- a/IRaCIS.Core.Application/Helper/OSSService.cs +++ b/IRaCIS.Core.Application/Helper/OSSService.cs @@ -143,9 +143,8 @@ public enum ObjectStoreUse public interface IOSSService { - public void SetImmediateArchiveRule(string prefix, - StorageClass targetStorageClass, - string ruleId = "immediate-archive"); + public Task SetImmediateArchiveRule(string prefix, string ruleId = "immediate-archive", bool isDelete = false); + public Task UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true); @@ -190,183 +189,576 @@ public class OSSService : IOSSService /// /// 将指定前缀下的所有现有文件立即转为目标存储类型 - /// 核心:Days = 0 表示对所有存量文件立即生效 /// /// 要转换的文件前缀,如 "project-a/logs/" - /// 目标存储类型 /// 规则ID,默认为"immediate-archive" - public void SetImmediateArchiveRule(string prefix, - StorageClass targetStorageClass, - string ruleId = "immediate-archive") + /// 默认是添加/更新 + public async Task SetImmediateArchiveRule(string prefix, string ruleId = "immediate-archive", bool isDelete = false) { BackBatchGetToken(); - var aliConfig = ObjectStoreServiceOptions.AliyunOSS; - - var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken); - - try + if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") { - // 1. 先获取现有的所有生命周期规则(避免覆盖) - var existingRules = new List(); + + + var aliConfig = ObjectStoreServiceOptions.AliyunOSS; + + var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken); + try { - var existingRuleList = _ossClient.GetBucketLifecycle(aliConfig.BucketName); - if (existingRuleList != null) + // 1. 先获取现有的所有生命周期规则(避免覆盖) + var existingRules = new List(); + try { - existingRules.AddRange(existingRuleList); - Console.WriteLine($"找到 {existingRules.Count} 条现有规则"); + var existingRuleList = _ossClient.GetBucketLifecycle(aliConfig.BucketName); + if (existingRuleList != null) + { + existingRules.AddRange(existingRuleList); + Console.WriteLine($"找到 {existingRules.Count} 条现有规则"); + } + } + catch (OssException ex) when (ex.ErrorCode == "NoSuchLifecycle") + { + // 如果没有生命周期规则,继续创建新规则 + Console.WriteLine("当前Bucket无生命周期规则,将创建新规则"); + } + + // 2. 创建立即生效的转换规则 + + ruleId = $"{ruleId}_{prefix}"; + var immediateRule = new Aliyun.OSS.LifecycleRule + { + ID = ruleId, + Prefix = prefix, + Status = RuleStatus.Enabled, + Transitions = new Aliyun.OSS.LifecycleRule.LifeCycleTransition[] + { + new Aliyun.OSS.LifecycleRule.LifeCycleTransition + { + + LifeCycleExpiration = + { + Days = 1 + }, + StorageClass = StorageClass.IA + }, + new Aliyun.OSS.LifecycleRule.LifeCycleTransition + { + + LifeCycleExpiration = + { + Days = 30 + }, + StorageClass = StorageClass.Archive + } + } + }; + + + + + // 3. 移除同名的旧规则(如果存在) + existingRules.RemoveAll(r => r.ID == ruleId); + + // 4. 添加新规则到规则列表 + if (isDelete == false) + { + existingRules.Add(immediateRule); + + } + + + + var request = new SetBucketLifecycleRequest(aliConfig.BucketName) + { + LifecycleRules = existingRules + }; + + + _ossClient.SetBucketLifecycle(request); + + + } + catch (OssException ex) + { + Log.Logger.Error($"❌ 设置失败 [错误码: {ex.ErrorCode}] 详细: {ex.Message}"); + + } + catch (Exception ex) + { + Log.Logger.Error($"❌ 发生未知错误: {ex.Message}"); + } + } + 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); + + // 1. 获取现有的生命周期配置(避免覆盖) + LifecycleConfiguration existingConfig = null; + + var getRequest = new GetLifecycleConfigurationRequest { BucketName = awsConfig.BucketName }; + var response = await amazonS3Client.GetLifecycleConfigurationAsync(getRequest); + existingConfig = response.Configuration; + Console.WriteLine($"找到 {existingConfig?.Rules?.Count ?? 0} 条现有规则"); + + // 2. 生成唯一的规则ID + ruleId = $"{ruleId}_{prefix.Replace('/', '_').Trim('_')}"; + + // 3. 创建新的生命周期规则 + var immediateRule = new Amazon.S3.Model.LifecycleRule + { + Id = ruleId, + Filter = new LifecycleFilter + { + // 使用前缀筛选对象 + LifecycleFilterPredicate = new LifecyclePrefixPredicate { Prefix = prefix } + }, + Status = LifecycleRuleStatus.Enabled, + // 定义多个转换阶段 + Transitions = new List + { + // 1天后转为低频访问 (Standard-IA) + new LifecycleTransition + { + Days = 1, + StorageClass = S3StorageClass.StandardInfrequentAccess // 对应S3 Standard-IA + }, + // 30天后转为归档 (Glacier Instant Retrieval) + new LifecycleTransition + { + Days = 30, + StorageClass = S3StorageClass.GlacierInstantRetrieval // 对应归档(即时检索) + } + // 如果需要更深的归档,可以继续添加: + // new LifecycleTransition { Days = 90, StorageClass = S3StorageClass.GlacierFlexibleRetrieval }, + // new LifecycleTransition { Days = 180, StorageClass = S3StorageClass.DeepArchive } + } + // 注意:S3的生命周期规则不支持设置“立即生效(Days=0)”。 + // 如果要对存量文件立即生效,需要配合其他方法(如批量修改存储类型)。 + }; + + // 4. 更新规则列表(移除同名旧规则,添加新规则) + var existingRules = existingConfig.Rules ?? new List(); + existingRules.RemoveAll(r => r.Id == ruleId); + + if (isDelete == false) + { + existingRules.Add(immediateRule); + + } + + // 5. 提交新的生命周期配置 + var putRequest = new PutLifecycleConfigurationRequest + { + BucketName = awsConfig.BucketName, + Configuration = new LifecycleConfiguration { Rules = existingRules } + }; + + await amazonS3Client.PutLifecycleConfigurationAsync(putRequest); + + } + else + { + throw new BusinessValidationFailedException("未定义的存储介质类型"); + } + } + + /// 解冻指定前缀下的所有归档/冷归档文件 + /// + /// 要解冻的文件前缀 + /// 解冻后文件保持可读的天数(默认3天) + /// 解冻优先级(仅AWS有效) + /// 批量处理大小(默认100) + public async Task RestoreFilesByPrefixAsync(string prefix, + int restoreDays = 3, + string restoreTier = "Standard", + int batchSize = 100) + { + BackBatchGetToken(); + + if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") + { + var aliConfig = ObjectStoreServiceOptions.AliyunOSS; + var client = new OssClient( + RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, + AliyunOSSTempToken.AccessKeyId, + AliyunOSSTempToken.AccessKeySecret, + AliyunOSSTempToken.SecurityToken + ); + + var bucketName = aliConfig.BucketName; + int totalRestored = 0; + int totalSkipped = 0; + int totalFailed = 0; + + try + { + Console.WriteLine($"开始解冻阿里云OSS文件,前缀: {prefix}"); + + // 1. 分页列举文件 + string nextMarker = null; + ObjectListing result = null; + + do + { + var listRequest = new Aliyun.OSS.ListObjectsRequest(bucketName) + { + Prefix = prefix, + Marker = nextMarker, + MaxKeys = batchSize + }; + + result = client.ListObjects(listRequest); + + // 2. 批量处理每个文件 + var restoreTasks = new List(); + + foreach (var obj in result.ObjectSummaries) + { + // 跳过非归档/冷归档文件 + if (obj.StorageClass != StorageClass.Archive.ToString()) + { + Console.WriteLine($"跳过非归档文件: {obj.Key} (类型: {obj.StorageClass})"); + totalSkipped++; + continue; + } + + // 提交解冻任务 + var task = Task.Run(() => + { + try + { + var restoreRequest = new Aliyun.OSS.RestoreObjectRequest(bucketName, obj.Key) + { + Days = restoreDays + }; + + client.RestoreObject(restoreRequest); + + Interlocked.Increment(ref totalRestored); + Console.WriteLine($"✅ 已提交解冻: {obj.Key} (天数: {restoreDays})"); + } + catch (OssException ex) + { + if (ex.ErrorCode == "RestoreAlreadyInProgress") + { + Console.WriteLine($"⚠️ 解冻已在进行中: {obj.Key}"); + } + else + { + Interlocked.Increment(ref totalFailed); + Console.WriteLine($"❌ 解冻失败 [{obj.Key}]: {ex.Message}"); + } + } + catch (Exception ex) + { + Interlocked.Increment(ref totalFailed); + Console.WriteLine($"❌ 解冻失败 [{obj.Key}]: {ex.Message}"); + } + }); + + restoreTasks.Add(task); + + // 控制并发,避免请求过快 + if (restoreTasks.Count >= 10) // 并发10个任务 + { + await Task.WhenAll(restoreTasks); + restoreTasks.Clear(); + await Task.Delay(100); // 短暂延迟 + } + } + + // 等待剩余任务完成 + if (restoreTasks.Count > 0) + { + await Task.WhenAll(restoreTasks); + } + + nextMarker = result.NextMarker; + + } while (result.IsTruncated); + + // 3. 输出统计结果 + Console.WriteLine("\n================ 解冻完成 ================"); + Console.WriteLine($"总计处理: {totalRestored + totalSkipped + totalFailed} 个文件"); + Console.WriteLine($"成功解冻: {totalRestored} 个"); + Console.WriteLine($"跳过文件: {totalSkipped} 个 (非归档类型)"); + Console.WriteLine($"解冻失败: {totalFailed} 个"); + + if (totalRestored > 0) + { + Console.WriteLine($"\n📋 解冻说明:"); + Console.WriteLine($" • 解冻任务已提交,文件将在后台处理"); + Console.WriteLine($" • 解冻完成后,文件将保持可读状态 {restoreDays} 天"); + Console.WriteLine($" • 归档文件约需1分钟,冷归档需数小时"); } } - catch (OssException ex) when (ex.ErrorCode == "NoSuchLifecycle") + catch (Exception ex) { - // 如果没有生命周期规则,继续创建新规则 - Console.WriteLine("当前Bucket无生命周期规则,将创建新规则"); + Log.Logger.Error($"❌ 阿里云解冻操作失败: {ex.Message}"); + throw; } + } + else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") + { + var awsConfig = ObjectStoreServiceOptions.AWS; + var credentials = new SessionAWSCredentials( + AWSTempToken.AccessKeyId, + AWSTempToken.SecretAccessKey, + AWSTempToken.SessionToken + ); - // 2. 创建立即生效的转换规则 + var clientConfig = new AmazonS3Config + { + RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region), + UseHttp = true, + }; + + using var client = new AmazonS3Client(credentials, clientConfig); + + var bucketName = awsConfig.BucketName; + int totalRestored = 0; + int totalSkipped = 0; + int totalFailed = 0; + + try + { + Console.WriteLine($"开始解冻AWS S3文件,前缀: {prefix}"); + + // 1. 分页列举文件 + string continuationToken = null; + ListObjectsV2Response response = null; + + do + { + var listRequest = new ListObjectsV2Request + { + BucketName = bucketName, + Prefix = prefix, + ContinuationToken = continuationToken, + MaxKeys = batchSize + }; + + response = await client.ListObjectsV2Async(listRequest); + + // 2. 批量处理每个文件 + var restoreTasks = new List(); + + foreach (var obj in response.S3Objects) + { + // 需要先获取对象元数据以确定存储类型 + var metadataRequest = new Amazon.S3.Model.GetObjectMetadataRequest + { + BucketName = bucketName, + Key = obj.Key + }; + + try + { + var metadata = await client.GetObjectMetadataAsync(metadataRequest); + + // 检查是否为归档类型 + bool isGlacierObject = metadata.StorageClass == S3StorageClass.Glacier; + + if (!isGlacierObject) + { + Console.WriteLine($"跳过非归档文件: {obj.Key} (类型: {metadata.StorageClass})"); + totalSkipped++; + continue; + } + + // 提交解冻任务 + var task = Task.Run(async () => + { + try + { + var restoreRequest = new Amazon.S3.Model.RestoreObjectRequest + { + BucketName = bucketName, + Key = obj.Key, + Days = restoreDays + }; + + await client.RestoreObjectAsync(restoreRequest); + + Interlocked.Increment(ref totalRestored); + Console.WriteLine($"✅ 已提交解冻: {obj.Key} (天数: {restoreDays}, 优先级: {restoreTier})"); + } + catch (AmazonS3Exception ex) + { + if (ex.ErrorCode == "RestoreAlreadyInProgress") + { + Console.WriteLine($"⚠️ 解冻已在进行中: {obj.Key}"); + } + else if (ex.ErrorCode == "AccessDenied") + { + Interlocked.Increment(ref totalFailed); + Console.WriteLine($"❌ 权限不足 [{obj.Key}]: 需要 s3:RestoreObject 权限"); + } + else + { + Interlocked.Increment(ref totalFailed); + Console.WriteLine($"❌ 解冻失败 [{obj.Key}]: {ex.Message}"); + } + } + catch (Exception ex) + { + Interlocked.Increment(ref totalFailed); + Console.WriteLine($"❌ 解冻失败 [{obj.Key}]: {ex.Message}"); + } + }); + + restoreTasks.Add(task); + + // 控制并发 + if (restoreTasks.Count >= 5) // AWS建议较低并发 + { + await Task.WhenAll(restoreTasks); + restoreTasks.Clear(); + await Task.Delay(200); // AWS有速率限制 + } + } + catch (Exception ex) + { + Console.WriteLine($"❌ 获取元数据失败 [{obj.Key}]: {ex.Message}"); + totalFailed++; + } + } + + // 等待剩余任务 + if (restoreTasks.Count > 0) + { + await Task.WhenAll(restoreTasks); + } + + continuationToken = response.NextContinuationToken; + + } while (response.IsTruncated == true); + + // 3. 输出统计结果 + Console.WriteLine("\n================ 解冻完成 ================"); + Console.WriteLine($"总计处理: {totalRestored + totalSkipped + totalFailed} 个文件"); + Console.WriteLine($"成功解冻: {totalRestored} 个"); + Console.WriteLine($"跳过文件: {totalSkipped} 个 (非归档类型)"); + Console.WriteLine($"解冻失败: {totalFailed} 个"); + + if (totalRestored > 0) + { + Console.WriteLine($"\n📋 AWS解冻说明:"); + Console.WriteLine($" • 解冻任务已提交到Glacier服务"); + Console.WriteLine($" • 标准解冻: 3-5小时 (Glacier Flexible Retrieval)"); + Console.WriteLine($" • 加急解冻: 1-5分钟 (额外收费)"); + Console.WriteLine($" • 解冻后文件可读 {restoreDays} 天"); + } + } + catch (Exception ex) + { + Log.Logger.Error($"❌ AWS解冻操作失败: {ex.Message}"); + throw; + } + } + else + { + throw new BusinessValidationFailedException("未定义的存储介质类型"); + } + } + + + /// + /// 坑方法,会清空之前的规则 + /// + /// + /// + /// + /// + public async Task SetLifecycle(string prefix, string ruleId = "immediate-archive") + { + BackBatchGetToken(); + + 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); ruleId = $"{ruleId}_{prefix}"; - var immediateRule = new Aliyun.OSS.LifecycleRule + var rule = new Aliyun.OSS.LifecycleRule { ID = ruleId, Prefix = prefix, Status = RuleStatus.Enabled, Transitions = new Aliyun.OSS.LifecycleRule.LifeCycleTransition[] - { + { new Aliyun.OSS.LifecycleRule.LifeCycleTransition { - + LifeCycleExpiration = { Days = 1 }, - StorageClass = targetStorageClass + StorageClass = StorageClass.IA + }, + new Aliyun.OSS.LifecycleRule.LifeCycleTransition + { + + LifeCycleExpiration = + { + Days = 30 + }, + StorageClass = StorageClass.Archive + } } - } }; - - - // 3. 移除同名的旧规则(如果存在) - existingRules.RemoveAll(r => r.ID == ruleId); - - // 4. 添加新规则到规则列表 - existingRules.Add(immediateRule); - - - var request = new SetBucketLifecycleRequest(aliConfig.BucketName) - { - LifecycleRules= existingRules - }; - + //会清空之前历史的规则,不能用。。。 + var request = new SetBucketLifecycleRequest(aliConfig.BucketName); + request.AddLifecycleRule(rule); _ossClient.SetBucketLifecycle(request); - Console.WriteLine("✅ 立即归档规则设置成功!"); - Console.WriteLine($" 规则ID: {ruleId}"); - Console.WriteLine($" 前缀: {prefix}"); - Console.WriteLine($" 目标存储类型: {targetStorageClass}"); - Console.WriteLine($" 生效时间: 将在下次生命周期扫描时生效(通常24小时内)"); - } - catch (OssException ex) - { - Console.WriteLine($"❌ 设置失败 [错误码: {ex.ErrorCode}]"); - Console.WriteLine($" 详细: {ex.Message}"); - // 处理特定错误 - if (ex.ErrorCode == "InvalidArgument") - { - Console.WriteLine(" 可能原因:存储类型不支持或参数格式错误"); - } } - catch (Exception ex) + else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") { - Console.WriteLine($"❌ 发生未知错误: {ex.Message}"); + 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); + + + } + else + { + throw new BusinessValidationFailedException("未定义的存储介质类型"); } } - - //public async Task SetLifecycle(string lifecycle) - //{ - - - // 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 rule = new Aliyun.OSS.LifecycleRule - // { - // ID = "ArchiveOldFiles", - // Prefix = "", // 全 bucket 生效 - // Status = RuleStatus.Enabled - // }; - - // // 30 天转低频 - // rule.Transitions.Add(new Aliyun.OSS.LifecycleRule.LifeCycleTransition - // { - // Days = 30, - // StorageClass = StorageClass.IA - // }); - - // // 180 天转归档 - // rule.Transitions.Add(new Aliyun.OSS.LifecycleRule.LifeCycleTransition - // { - // Days = 180, - // StorageClass = StorageClass.Archive - // }); - - // // 365 天转冷归档 - // rule.Transitions.Add(new Aliyun.OSS.LifecycleRule.LifeCycleTransition - // { - // Days = 365, - // StorageClass = StorageClass.ColdArchive - // }); - - // // 730 天转深度归档 - // rule.Transitions.Add(new Aliyun.OSS.LifecycleRule.LifeCycleTransition - // { - // Days = 730, - // StorageClass = StorageClass.DeepColdArchive - // }); - - // var request = new SetBucketLifecycleRequest(aliConfig.BucketName); - // request.AddLifecycleRule(rule); - - // _ossClient.SetBucketLifecycle(request); - - - // } - // 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); - - - // } - // else - // { - // throw new BusinessValidationFailedException("未定义的存储介质类型"); - // } - //} - /// /// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder /// @@ -705,7 +1097,7 @@ public class OSSService : IOSSService .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey) .WithSSL(minIOConfig.UseSSL) .Build(); - + var pipe = new System.IO.Pipelines.Pipe(); _ = Task.Run(async () => diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index 6abd62171..a790082c6 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -15740,14 +15740,23 @@ 利用DocX 库 处理word国际化模板 - + 将指定前缀下的所有现有文件立即转为目标存储类型 - 核心:Days = 0 表示对所有存量文件立即生效 要转换的文件前缀,如 "project-a/logs/" - 目标存储类型 规则ID,默认为"immediate-archive" + 默认是添加/更新 + + + + + 坑方法,会清空之前的规则 + + + + + diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs index 837b312a4..c9ffcb172 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs @@ -1,4 +1,5 @@ -using IRaCIS.Application.Contracts; +using Aliyun.OSS; +using IRaCIS.Application.Contracts; using IRaCIS.Application.Interfaces; using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Filter; @@ -32,7 +33,7 @@ namespace IRaCIS.Core.Application IRepository _clinicalDataTrialSetRepository, IRepository _readingCriterionPageRepository, IRepository _systemCriterionKeyFileRepository, - IOSSService oSSService, + IOSSService _oSSService, IRepository _trialCriterionKeyFileRepository, IOrganInfoService _iOrganInfoService, IRepository _trialBodyPartRepository, @@ -331,22 +332,22 @@ namespace IRaCIS.Core.Application public async Task SynchronizeKeyFile(Guid TrialReadingCriterionId) { var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == TrialReadingCriterionId).AsNoTracking().FirstOrDefaultAsync(); - if (trialCriterion != null && trialCriterion.ReadingQuestionCriterionSystemId!=null) + if (trialCriterion != null && trialCriterion.ReadingQuestionCriterionSystemId != null) { var systemCriterionKeyFile = await _systemCriterionKeyFileRepository.Where(x => x.SystemCriterionId == trialCriterion.ReadingQuestionCriterionSystemId).ToListAsync(); - List trialCriterionKeyFiles= new List(); + List trialCriterionKeyFiles = new List(); - foreach (var item in systemCriterionKeyFile) + foreach (var item in systemCriterionKeyFile) { - var path= await oSSService.UploadToOSSAsync(item.FilePath, $"{trialCriterion.TrialId}/ReadingModule/{trialCriterion.CriterionName}", true,true); + var path = await _oSSService.UploadToOSSAsync(item.FilePath, $"{trialCriterion.TrialId}/ReadingModule/{trialCriterion.CriterionName}", true, true); trialCriterionKeyFiles.Add(new TrialCriterionKeyFile { - TrialCriterionId= TrialReadingCriterionId, - FileName= item.FileName, - FilePath= path + TrialCriterionId = TrialReadingCriterionId, + FileName = item.FileName, + FilePath = path }); } @@ -1325,6 +1326,18 @@ namespace IRaCIS.Core.Application await _trialRepository.BatchUpdateNoTrackingAsync(u => u.Id == trialId, s => new Trial { TrialFinishedTime = DateTime.Now }); + + if (_readingQuestionCriterionTrialRepository.Any(t => t.IsSigned && t.ImageUploadEnum != ReadingImageUpload.None)) + { + await _oSSService.SetImmediateArchiveRule($"{trial.Id}/Image/"); + await _oSSService.SetImmediateArchiveRule($"{trial.Id}/TaskImage/"); + + } + else + { + await _oSSService.SetImmediateArchiveRule($"{trial.Id}/Image/"); + } + } await _fusionCache.SetAsync(CacheKeys.Trial(trial.Id.ToString()), trialStatusStr, TimeSpan.FromDays(7)); @@ -1546,7 +1559,7 @@ namespace IRaCIS.Core.Application [AllowAnonymous] public async Task GetTrialExtralConfig(Guid trialId) { - var extralObj = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.TrialExtraConfigJsonStr,t.IsExternalViewTrialChart, t.TrialObjectNameList, t.CollectImagesEnum, t.IsIQCAutoNextTask }).FirstOrDefault(); + var extralObj = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.TrialExtraConfigJsonStr, t.IsExternalViewTrialChart, t.TrialObjectNameList, t.CollectImagesEnum, t.IsIQCAutoNextTask }).FirstOrDefault(); var extralConfig = JsonConvert.DeserializeObject(extralObj?.TrialExtraConfigJsonStr) ?? new TrialExtraConfig(); diff --git a/IRaCIS.Core.Application/TestService.cs b/IRaCIS.Core.Application/TestService.cs index 43dcbbacb..be1248356 100644 --- a/IRaCIS.Core.Application/TestService.cs +++ b/IRaCIS.Core.Application/TestService.cs @@ -80,7 +80,7 @@ namespace IRaCIS.Core.Application.Service { if (storageClass == StorageClass.IA || storageClass == StorageClass.Archive || storageClass == StorageClass.ColdArchive || storageClass == StorageClass.DeepColdArchive) { - _IOSSService.SetImmediateArchiveRule($"Test-Archive/Archive{(int)storageClass}", storageClass); + _IOSSService.SetImmediateArchiveRule($"Test-Archive/Archive{(int)storageClass}/"); }