Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is running
Details
continuous-integration/drone/push Build is running
Details
commit
e559c2503b
|
|
@ -65,7 +65,8 @@ SerilogExtension.AddSerilogSetup(enviromentName);
|
|||
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
|
||||
{
|
||||
|
||||
EnvironmentName = enviromentName
|
||||
EnvironmentName = enviromentName,
|
||||
Args = args
|
||||
});
|
||||
|
||||
#region 主机配置
|
||||
|
|
|
|||
|
|
@ -33,11 +33,11 @@
|
|||
},
|
||||
"applicationUrl": "http://0.0.0.0:6100"
|
||||
},
|
||||
"IRaCIS.Event_IRC": {
|
||||
"IRaCIS.Prod_Event_IRC": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Event_IRC"
|
||||
"ASPNETCORE_ENVIRONMENT": "Prod_Event_IRC"
|
||||
},
|
||||
"applicationUrl": "http://0.0.0.0:6100"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,8 +7,10 @@
|
|||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=101.132.253.119,1435;Database=irc_Prpd_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=101.132.253.119,1435;Database=irc_Hangfire_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
"RemoteNew": "Server=10.10.10.49,1433;Database=Prod_IRC_pidr_restore;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=10.10.10.49,1433;Database=irc_Hangfire_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
//"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
|
||||
//"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
|
||||
},
|
||||
"WeComNoticeConfig": {
|
||||
"IsOpenWeComNotice": true,
|
||||
|
|
@ -17,48 +19,51 @@
|
|||
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ]
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
|
||||
"IsOpenStoreSync": true,
|
||||
"ApiDeployRegion": "CN",
|
||||
"SyncConfigList": [
|
||||
{
|
||||
"Domain": "irc.extimaging.com",
|
||||
"Primary": "AliyunOSS",
|
||||
"Target": "AWS",
|
||||
"UploadRegion": "CN",
|
||||
"TargetRegion": "US",
|
||||
"IsOpenSync": true
|
||||
},
|
||||
{
|
||||
"Domain": "eiirc.extimaging.com",
|
||||
"Primary": "AWS",
|
||||
"Target": "AliyunOSS",
|
||||
"UploadRegion": "US",
|
||||
"TargetRegion": "CN",
|
||||
"IsOpenSync": true
|
||||
}
|
||||
],
|
||||
"AliyunOSS": {
|
||||
"RegionId": "cn-shanghai",
|
||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"AccessKeyId": "LTAI5tFUCCmz5TwghZHsj45Y",
|
||||
"AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T",
|
||||
"RoleArn": "acs:ram::1078130221702011:role/uat-oss-access",
|
||||
"BucketName": "tl-med-irc-event-store",
|
||||
"ViewEndpoint": "https://tl-med-irc-event-store.oss-cn-shanghai.aliyuncs.com",
|
||||
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
|
||||
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
|
||||
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
|
||||
"BucketName": "zy-irc-store",
|
||||
"ViewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
||||
"Region": "oss-cn-shanghai",
|
||||
"DurationSeconds": 7200
|
||||
},
|
||||
|
||||
"MinIO": {
|
||||
"endPoint": "hir-oss.uat.extimaging.com",
|
||||
"port": "80",
|
||||
"useSSL": false,
|
||||
"viewEndpoint": "http://hir-oss.uat.extimaging.com/irc-uat",
|
||||
//"port": "443",
|
||||
//"useSSL": true,
|
||||
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/irc-uat",
|
||||
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
|
||||
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
|
||||
"bucketName": "irc-uat"
|
||||
|
||||
},
|
||||
"AWS": {
|
||||
"Region": "us-east-1",
|
||||
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||
"UseSSL": true,
|
||||
"RoleArn": "arn:aws:iam::471112624751:role/sts_s3_upload",
|
||||
"AccessKeyId": "AKIAW3MEAFJXWRCGSX5Z",
|
||||
"SecretAccessKey": "miais4jQGSd37A+TfBEP11AQM5u/CvotSmznJd8k",
|
||||
"BucketName": "ei-med-s3-lili-uat-store",
|
||||
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
|
||||
"RoleArn": "arn:aws:iam::471112624751:role/lili_s3_access",
|
||||
"AccessKeyId": "AKIAW3MEAFJXZ2TZK7GM",
|
||||
"SecretAccessKey": "9MLQCQ1HifEVW1gf068zBRAOb4wNnfrOkvBVByth",
|
||||
"BucketName": "ei-med-s3-irc-store",
|
||||
"ViewEndpoint": "https://ei-med-s3-irc-store.s3.amazonaws.com",
|
||||
"DurationSeconds": 7200
|
||||
}
|
||||
},
|
||||
|
||||
"BasicSystemConfig": {
|
||||
// 启用质控风险控制功能
|
||||
"QCRiskControl": true,
|
||||
|
|
@ -67,7 +72,6 @@
|
|||
|
||||
"OpenLoginLimit": true,
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30,
|
||||
"AutoLoginOutMinutes": 120,
|
||||
|
||||
|
|
@ -82,17 +86,17 @@
|
|||
"TemplateType": 2,
|
||||
//MFA免验证发送天数
|
||||
"UserMFAVerifyMinutes": 1440
|
||||
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"Imap": "imap.qiye.aliyun.com",
|
||||
"ImapPort": 993,
|
||||
"FromEmail": "uat@extimaging.com",
|
||||
"FromName": "Uat IRC Imaging System",
|
||||
"AuthorizationCode": "SHzyyl2021",
|
||||
"SiteUrl": "http://irc.uat.extimaging.com/login",
|
||||
"FromEmail": "irc@extimaging.com",
|
||||
"FromName": "IRC Imaging System",
|
||||
"AuthorizationCode": "ExtImg@2022",
|
||||
"SiteUrl": "http://irc.extimaging.com/login",
|
||||
|
||||
"PlatformName": "EICS",
|
||||
"PlatformNameCN": "展影云平台",
|
||||
|
|
@ -104,15 +108,12 @@
|
|||
"CompanyShortName": "Extensive Imaging",
|
||||
"CompanyShortNameCN": "展影医疗",
|
||||
"IsEnv_US": false,
|
||||
"IsOpenErrorNoticeEmail": false,
|
||||
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
||||
"CronEmailDefaultCulture": "zh-CN",
|
||||
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
|
||||
"CronEmailDefaultCulture": "zh-CN"
|
||||
},
|
||||
|
||||
"SystemPacsConfig": {
|
||||
"Port": "11116",
|
||||
"IP": "101.132.253.119"
|
||||
"Port": "11113",
|
||||
"IP": "101.132.193.237"
|
||||
},
|
||||
"RequestDuplicationOptions": {
|
||||
"IsEnabled": true,
|
||||
|
|
|
|||
|
|
@ -1767,11 +1767,13 @@
|
|||
<param name="_trialRepository"></param>
|
||||
<param name="_oSSService"></param>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Service.TrialImageDownloadService.DownloadTrialImage(System.Guid)">
|
||||
<member name="M:IRaCIS.Core.Application.Service.TrialImageDownloadService.DownloadTrialImage(System.Guid,System.Int32,System.Int32)">
|
||||
<summary>
|
||||
后端api swagger 下载项目影像
|
||||
</summary>
|
||||
<param name="trialId"></param>
|
||||
<param name="startIndex"></param>
|
||||
<param name="endIndex"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Service.TrialImageDownloadService.DownloadAndUploadTrialData(System.Guid,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomSeries})">
|
||||
|
|
@ -17494,17 +17496,17 @@
|
|||
</member>
|
||||
<member name="F:IRaCIS.Core.Application.ViewModel.AccessToDialogueEnum.Question">
|
||||
<summary>
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
质疑
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:IRaCIS.Core.Application.ViewModel.AccessToDialogueEnum.Consistency">
|
||||
<summary>
|
||||
һ<EFBFBD><EFBFBD><EFBFBD>Ժ˲<EFBFBD>
|
||||
一致性核查
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:IRaCIS.Core.Application.ViewModel.CopyFrontAuditConfigItemDto">
|
||||
<summary>
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
复制
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:IRaCIS.Core.Application.ViewModel.SystemNoticeView">
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using FellowOakDicom.Imaging;
|
|||
using FellowOakDicom.Imaging.Render;
|
||||
using FellowOakDicom.IO.Buffer;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Application.MassTransit.Command;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
|
|
@ -18,17 +19,20 @@ using Microsoft.AspNetCore.Hosting;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using MiniExcelLibs;
|
||||
using NPOI.Util;
|
||||
using Org.BouncyCastle.Utilities.Zlib;
|
||||
using SharpCompress.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using static IRaCIS.Core.Application.Service.TestService;
|
||||
using static IRaCIS.Core.Domain.Share.StaticData;
|
||||
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
|
||||
|
||||
|
|
@ -97,30 +101,101 @@ namespace IRaCIS.Core.Application.Service
|
|||
}
|
||||
|
||||
|
||||
|
||||
public static class DownloadLogger
|
||||
{
|
||||
|
||||
|
||||
public static void Write(
|
||||
string logFilePath,
|
||||
string subjectCode,
|
||||
decimal visitNum,
|
||||
string visitName,
|
||||
string? message = null)
|
||||
{
|
||||
|
||||
bool fileExists = File.Exists(logFilePath);
|
||||
|
||||
using var stream = new FileStream(
|
||||
logFilePath,
|
||||
FileMode.Append,
|
||||
FileAccess.Write,
|
||||
FileShare.ReadWrite);
|
||||
|
||||
using var writer = new StreamWriter(stream, Encoding.UTF8);
|
||||
|
||||
|
||||
// 首次写入表头
|
||||
if (!fileExists)
|
||||
{
|
||||
writer.WriteLine("Time,SubjectCode,VisitNum,VisitName,Message");
|
||||
}
|
||||
|
||||
string line = string.Join(",",
|
||||
[
|
||||
Escape(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")),
|
||||
subjectCode,
|
||||
visitNum,
|
||||
visitName,
|
||||
Escape(message)
|
||||
]);
|
||||
|
||||
writer.WriteLine(line);
|
||||
}
|
||||
|
||||
// 防止逗号、换行导致 CSV 错乱
|
||||
private static string Escape(string? value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return "";
|
||||
|
||||
value = value.Replace("\"", "\"\"");
|
||||
|
||||
return $"\"{value}\"";
|
||||
}
|
||||
}
|
||||
|
||||
public class DownloadJob
|
||||
{
|
||||
public bool IsZip { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
|
||||
public Func<Task> Action { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 后端api swagger 下载项目影像
|
||||
/// </summary>
|
||||
/// <param name="trialId"></param>
|
||||
/// <param name="startIndex"></param>
|
||||
/// <param name="endIndex"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
public async Task<IResponseOutput> DownloadTrialImage(Guid trialId)
|
||||
public async Task<IResponseOutput> DownloadTrialImage(Guid trialId, int startIndex, int endIndex)
|
||||
{
|
||||
//找到项目里面未阅片的影像
|
||||
|
||||
if (startIndex < 1 || endIndex < 1 || startIndex > endIndex)
|
||||
{
|
||||
return ResponseOutput.NotOk("请输入正确的下载区间");
|
||||
}
|
||||
|
||||
|
||||
//var subjectCodeList = new List<string>() { "05002", "07006", "07026" };
|
||||
var downloadInfo = _trialRepository.Where(t => t.Id == trialId).Select(t => new
|
||||
{
|
||||
t.ResearchProgramNo,
|
||||
|
||||
VisitList = t.SubjectVisitList
|
||||
VisitList = t.SubjectVisitList.Where(t => t.VisitTaskList.Any(t => t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Visit && t.ReadingTaskState != ReadingTaskState.HaveSigned && t.SourceSubjectVisitId != null && t.DoctorUserId != null))
|
||||
//.Where(t=>subjectCodeList.Contains(t.Subject.Code))
|
||||
.Select(sv => new
|
||||
{
|
||||
TrialSiteCode = sv.TrialSite.TrialSiteCode,
|
||||
SubjectCode = sv.Subject.Code,
|
||||
VisitName = sv.VisitName,
|
||||
VisitNum = sv.VisitNum,
|
||||
StudyList = sv.StudyList.Select(u => new
|
||||
{
|
||||
u.PatientId,
|
||||
|
|
@ -154,159 +229,268 @@ namespace IRaCIS.Core.Application.Service
|
|||
file.FileType
|
||||
}).ToList()
|
||||
}).ToList()
|
||||
}).ToList()
|
||||
}).OrderBy(t => t.SubjectCode).ThenBy(t => t.VisitNum).ToList()
|
||||
|
||||
}).FirstOrDefault();
|
||||
|
||||
|
||||
var count = downloadInfo.VisitList.SelectMany(t => t.NoneDicomStudyList).SelectMany(t => t.FileList).Count();
|
||||
var count2 = downloadInfo.VisitList.SelectMany(t => t.StudyList).SelectMany(t => t.SeriesList).SelectMany(t => t.InstancePathList).Count();
|
||||
|
||||
Console.WriteLine($"下载总数量:{count}+{count2}={count + count2}");
|
||||
|
||||
if (downloadInfo != null)
|
||||
if (downloadInfo == null)
|
||||
{
|
||||
var downloadJobs = new List<Func<Task>>();
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
//var rootFolder = @"E:\DownloadImage";
|
||||
#region 设置目录
|
||||
|
||||
var rootFolder = FileStoreHelper.GetDonwnloadImageFolder(_hostEnvironment);
|
||||
var rootFolder = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||
Directory.CreateDirectory(rootFolder);
|
||||
|
||||
// 获取无效字符(系统定义的)
|
||||
string invalidChars = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
|
||||
// 获取无效字符(系统定义的)
|
||||
string invalidChars = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
|
||||
|
||||
// 用正则表达式替换所有非法字符为下划线或空字符
|
||||
string pattern = $"[{Regex.Escape(invalidChars)}]";
|
||||
// 用正则表达式替换所有非法字符为下划线或空字符
|
||||
string pattern = $"[{Regex.Escape(invalidChars)}]";
|
||||
|
||||
var regexNo = Regex.Replace(downloadInfo.ResearchProgramNo, pattern, "_");
|
||||
var regexNo = Regex.Replace(downloadInfo.ResearchProgramNo, pattern, "_");
|
||||
|
||||
// 创建一个临时文件夹来存放文件
|
||||
string trialFolderPath = Path.Combine(rootFolder, $"{regexNo}_{NewId.NextGuid()}");
|
||||
Directory.CreateDirectory(trialFolderPath);
|
||||
// 创建一个临时文件夹来存放文件
|
||||
string trialFolderPath = Path.Combine(rootFolder, $"{regexNo}");//_{NewId.NextGuid()}
|
||||
Directory.CreateDirectory(trialFolderPath);
|
||||
|
||||
foreach (var visitItem in downloadInfo.VisitList)
|
||||
var oldVisits = MiniExcel.Query<SubjectVisitExcel>(Path.Combine(rootFolder, "Old.xlsx")).ToList();
|
||||
|
||||
Log.Logger.Warning($"数据库查询下载访视数量 - 前一批已下载访视数量:{downloadInfo.VisitList.Count} - {oldVisits.Count}");
|
||||
|
||||
var acturalDownList = downloadInfo.VisitList.Where(t => !oldVisits.Any(old => old.VisitNum == t.VisitNum && old.SubjectCode == t.SubjectCode &&
|
||||
old.VisitName.Trim().ToLower() == t.VisitName.Trim().ToLower())).ToList();
|
||||
|
||||
#endregion
|
||||
|
||||
#region 排除已经下载的
|
||||
|
||||
var logFilePath = Path.Combine(rootFolder, $"{trialId}_{regexNo}_download_log.csv");
|
||||
|
||||
if (File.Exists(logFilePath))
|
||||
{
|
||||
var existVisits = MiniExcel.Query<SubjectVisitExcel>(logFilePath, configuration: new MiniExcelLibs.Csv.CsvConfiguration()
|
||||
{
|
||||
if (visitItem.StudyList.Count() == 0 && visitItem.NoneDicomStudyList.Count() == 0)
|
||||
StreamReaderFunc = (stream) => new StreamReader(stream, Encoding.GetEncoding("gb2312"))
|
||||
}).ToList();
|
||||
|
||||
Log.Logger.Warning($"download_log.csv访视数量:{existVisits.Count}");
|
||||
|
||||
Log.Logger.Warning($"csv排除前需要下载数量:{acturalDownList.Count}");
|
||||
|
||||
acturalDownList = acturalDownList.Where(t => !existVisits.Any(old => old.VisitNum == t.VisitNum && old.SubjectCode == t.SubjectCode &&
|
||||
old.VisitName.Trim().ToLower() == t.VisitName.Trim().ToLower())).ToList();
|
||||
|
||||
Log.Logger.Warning($"csv排除后需要下载数量:{acturalDownList.Count}");
|
||||
|
||||
|
||||
}
|
||||
|
||||
acturalDownList = acturalDownList.Skip(startIndex - 1).Take(endIndex - startIndex + 1).ToList();
|
||||
|
||||
Log.Logger.Warning($"该区{startIndex}-{endIndex} 实际需要下载访视数量:{acturalDownList.Count}");
|
||||
|
||||
#endregion
|
||||
|
||||
var count = acturalDownList.SelectMany(t => t.NoneDicomStudyList).SelectMany(t => t.FileList).Count();
|
||||
|
||||
var count2 = acturalDownList.SelectMany(t => t.StudyList).SelectMany(t => t.SeriesList).SelectMany(t => t.InstancePathList).Count();
|
||||
|
||||
Log.Logger.Warning($"下载总数量:{count}+{count2}={count + count2}");
|
||||
|
||||
var downloadJobs = new List<DownloadJob>();
|
||||
|
||||
foreach (var visitItem in acturalDownList)
|
||||
{
|
||||
if (visitItem.StudyList.Count() == 0 && visitItem.NoneDicomStudyList.Count() == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
#region 处理 中心,受试者dicom non-dicom 文件夹层级
|
||||
|
||||
//var siteFolderPath = Path.Combine(trialFolderPath, visitItem.TrialSiteCode);
|
||||
//if (!Directory.Exists(siteFolderPath))
|
||||
//{
|
||||
// Directory.CreateDirectory(siteFolderPath);
|
||||
//}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
foreach (var studyInfo in visitItem.StudyList)
|
||||
{
|
||||
// 遍历 Series
|
||||
foreach (var seriesInfo in studyInfo.SeriesList)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
string studyDicomFolderPath = Path.Combine(trialFolderPath, $"{visitItem.SubjectCode}_{visitItem.VisitName.Trim()}", $"{studyInfo.StudyCode}_{studyInfo.StudyTime?.ToString("yyyy-MM-dd")}_{seriesInfo.Modality}");
|
||||
|
||||
#region 处理 中心,受试者dicom non-dicom 文件夹层级
|
||||
// 创建 影像 文件夹
|
||||
Directory.CreateDirectory(studyDicomFolderPath);
|
||||
|
||||
var siteFolderPath = Path.Combine(trialFolderPath, visitItem.TrialSiteCode);
|
||||
if (!Directory.Exists(siteFolderPath))
|
||||
{
|
||||
Directory.CreateDirectory(siteFolderPath);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
foreach (var studyInfo in visitItem.StudyList)
|
||||
{
|
||||
// 遍历 Series
|
||||
foreach (var seriesInfo in studyInfo.SeriesList)
|
||||
// 遍历 InstancePathList
|
||||
foreach (var instanceInfo in seriesInfo.InstancePathList)
|
||||
{
|
||||
string studyDicomFolderPath = Path.Combine(siteFolderPath, $"{visitItem.SubjectCode}_{visitItem.VisitName}_DICOM", $"{studyInfo.StudyCode}_{studyInfo.StudyTime?.ToString("yyyy-MM-dd")}_{seriesInfo.Modality}");
|
||||
// 复制文件到相应的文件夹
|
||||
string destinationPath = Path.Combine(studyDicomFolderPath, Path.GetFileName(instanceInfo.Path));
|
||||
|
||||
// 创建 影像 文件夹
|
||||
Directory.CreateDirectory(studyDicomFolderPath);
|
||||
|
||||
// 遍历 InstancePathList
|
||||
foreach (var instanceInfo in seriesInfo.InstancePathList)
|
||||
downloadJobs.Add(new DownloadJob()
|
||||
{
|
||||
// 复制文件到相应的文件夹
|
||||
string destinationPath = Path.Combine(studyDicomFolderPath, Path.GetFileName(instanceInfo.Path));
|
||||
Name = $"{visitItem.SubjectCode}_{visitItem.VisitNum}_{visitItem.VisitName.Trim()}_DICOM_{destinationPath}",
|
||||
|
||||
Action = async () =>
|
||||
{
|
||||
await using var output = File.Create(destinationPath);
|
||||
|
||||
if (instanceInfo.IsEncapsulated)
|
||||
{
|
||||
//加入到下载任务里
|
||||
downloadJobs.Add(() => TryWriteMergedDicomAsync(() => _oSSService.GetStreamFromOSSAsync(instanceInfo.Path), output));
|
||||
await TryWriteMergedDicomAsync(
|
||||
() => _oSSService.GetStreamFromOSSAsync(instanceInfo.Path),
|
||||
output);
|
||||
}
|
||||
else
|
||||
{
|
||||
//加入到下载任务里
|
||||
downloadJobs.Add(() => _oSSService.DownLoadFromOSSAsync(instanceInfo.Path, destinationPath));
|
||||
await using var input =
|
||||
await _oSSService.GetStreamFromOSSAsync(instanceInfo.Path);
|
||||
|
||||
await input.CopyToAsync(output);
|
||||
}
|
||||
|
||||
|
||||
//下载到当前目录
|
||||
//await _oSSService.DownLoadFromOSSAsync(instanceInfo.Path, destinationPath);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
foreach (var noneDicomStudy in visitItem.NoneDicomStudyList)
|
||||
{
|
||||
string studyNoneDicomFolderPath = Path.Combine(siteFolderPath, $"{visitItem.SubjectCode}_{visitItem.VisitName}_Non-DICOM", $"{noneDicomStudy.StudyCode}_{noneDicomStudy.ImageDate.ToString("yyyy-MM-dd")}_{noneDicomStudy.Modality}");
|
||||
|
||||
Directory.CreateDirectory(studyNoneDicomFolderPath);
|
||||
|
||||
foreach (var file in noneDicomStudy.FileList)
|
||||
{
|
||||
string destinationPath = Path.Combine(studyNoneDicomFolderPath, Path.GetFileName(file.FileName));
|
||||
|
||||
//加入到下载任务里
|
||||
downloadJobs.Add(() => _oSSService.DownLoadFromOSSAsync(HttpUtility.UrlDecode(file.Path), destinationPath));
|
||||
//下载到当前目录
|
||||
//await _oSSService.DownLoadFromOSSAsync(HttpUtility.UrlDecode(file.Path), destinationPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#region 异步方式处理
|
||||
|
||||
int totalCount = downloadJobs.Count;
|
||||
int downloadedCount = 0;
|
||||
|
||||
foreach (var job in downloadJobs)
|
||||
foreach (var noneDicomStudy in visitItem.NoneDicomStudyList)
|
||||
{
|
||||
try
|
||||
string studyNoneDicomFolderPath = Path.Combine(trialFolderPath, $"{visitItem.SubjectCode}_{visitItem.VisitName.Trim()}", $"{noneDicomStudy.StudyCode}_{noneDicomStudy.ImageDate.ToString("yyyy-MM-dd")}_{noneDicomStudy.Modality}");
|
||||
|
||||
Directory.CreateDirectory(studyNoneDicomFolderPath);
|
||||
|
||||
foreach (var file in noneDicomStudy.FileList)
|
||||
{
|
||||
await job();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Logger.Error($"下载失败: {ex.Message}");
|
||||
}
|
||||
string destinationPath = Path.Combine(studyNoneDicomFolderPath, Path.GetFileName(file.FileName));
|
||||
|
||||
downloadedCount++;
|
||||
|
||||
// 每处理50个,输出一次进度(或最后一个时也输出)
|
||||
if (downloadedCount % 50 == 0 || downloadedCount == totalCount)
|
||||
{
|
||||
|
||||
Log.Logger.Error($"已下载 {downloadedCount} / {totalCount} 个文件,完成 {(downloadedCount * 100.0 / totalCount):F2}%");
|
||||
//加入到下载任务里
|
||||
downloadJobs.Add(new DownloadJob() { Name = $"{visitItem.SubjectCode}_{visitItem.VisitNum}_{visitItem.VisitName.Trim()}_NoneDICOM_{destinationPath}", Action = () => _oSSService.DownLoadFromOSSAsync(HttpUtility.UrlDecode(file.Path), destinationPath) });
|
||||
|
||||
//下载到当前目录
|
||||
//await _oSSService.DownLoadFromOSSAsync(HttpUtility.UrlDecode(file.Path), destinationPath);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 多线程测试
|
||||
|
||||
//const int batchSize = 15;
|
||||
//int totalCount = downloadJobs.Count;
|
||||
//int downloadedCount = 0;
|
||||
//建立压缩包
|
||||
string visitFolderPath = Path.Combine(trialFolderPath, $"{visitItem.SubjectCode}_{visitItem.VisitName.Trim()}");
|
||||
|
||||
//for (int i = 0; i < downloadJobs.Count; i += batchSize)
|
||||
//{
|
||||
// var batch = downloadJobs.Skip(i).Take(batchSize).Select(job => job());
|
||||
downloadJobs.Add(new DownloadJob()
|
||||
{
|
||||
Name = $"{visitItem.SubjectCode}_{visitItem.VisitName.Trim()}_Zip",
|
||||
|
||||
// await Task.WhenAll(batch);
|
||||
IsZip = true,
|
||||
|
||||
// downloadedCount += batch.Count();
|
||||
Action = async () =>
|
||||
{
|
||||
string zipPath = visitFolderPath + ".zip";
|
||||
|
||||
// Console.WriteLine($"已下载 {downloadedCount} / {totalCount} 个文件,完成 {(downloadedCount * 100.0 / totalCount):F2}%");
|
||||
//}
|
||||
#endregion
|
||||
if (File.Exists(zipPath))
|
||||
{
|
||||
File.Delete(zipPath);
|
||||
}
|
||||
|
||||
ZipFile.CreateFromDirectory(
|
||||
visitFolderPath,
|
||||
zipPath,
|
||||
CompressionLevel.NoCompression,
|
||||
false);
|
||||
|
||||
Directory.Delete(visitFolderPath, true);
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
});
|
||||
|
||||
//记录日志
|
||||
downloadJobs.Add(new DownloadJob()
|
||||
{
|
||||
Name = $"{visitItem.SubjectCode}_{visitItem.VisitNum}_{visitItem.VisitName.Trim()}_Finished",
|
||||
Action = () =>
|
||||
{
|
||||
DownloadLogger.Write(
|
||||
logFilePath: logFilePath,
|
||||
subjectCode: visitItem.SubjectCode,
|
||||
visitNum: visitItem.VisitNum,
|
||||
visitName: visitItem.VisitName.Trim(),
|
||||
message: "Success");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#region 异步方式处理
|
||||
|
||||
int totalCount = downloadJobs.Count;
|
||||
int downloadedCount = 0;
|
||||
|
||||
foreach (var job in downloadJobs)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (job.IsZip == false)
|
||||
{
|
||||
await job.Action();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
await job.Action();
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Logger.Error($"{job.Name}下载失败: {ex.Message}");
|
||||
}
|
||||
|
||||
downloadedCount++;
|
||||
|
||||
// 每处理50个,输出一次进度(或最后一个时也输出)
|
||||
if (downloadedCount % 50 == 0 || downloadedCount == totalCount)
|
||||
{
|
||||
|
||||
Log.Logger.Warning($"已下载 {downloadedCount} / {totalCount} 个文件,完成 {(downloadedCount * 100.0 / totalCount):F2}%");
|
||||
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 多线程测试
|
||||
|
||||
//const int batchSize = 15;
|
||||
//int totalCount = downloadJobs.Count;
|
||||
//int downloadedCount = 0;
|
||||
|
||||
//for (int i = 0; i < downloadJobs.Count; i += batchSize)
|
||||
//{
|
||||
// var batch = downloadJobs.Skip(i).Take(batchSize).Select(job => job());
|
||||
|
||||
// await Task.WhenAll(batch);
|
||||
|
||||
// downloadedCount += batch.Count();
|
||||
|
||||
// Console.WriteLine($"已下载 {downloadedCount} / {totalCount} 个文件,完成 {(downloadedCount * 100.0 / totalCount):F2}%");
|
||||
//}
|
||||
#endregion
|
||||
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue