diff --git a/IRaCIS.Core.Application/Helper/DicomDIRHelper.cs b/IRaCIS.Core.Application/Helper/DicomDIRHelper.cs index dd3b7c140..f41bd13cd 100644 --- a/IRaCIS.Core.Application/Helper/DicomDIRHelper.cs +++ b/IRaCIS.Core.Application/Helper/DicomDIRHelper.cs @@ -3,6 +3,7 @@ using FellowOakDicom; using FellowOakDicom.Media; using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Domain.Models; +using NPOI.Util; using System; using System.Collections.Generic; using System.Data; @@ -160,7 +161,7 @@ namespace IRaCIS.Core.Application.Helper } - public static async Task GenerateStudyDIR(List list, Dictionary dic,string dirSavePath) + public static async Task GenerateStudyDIR(List list, Dictionary dic, string? dirSavePath = null, Stream? outputStream = null) { var mappings = new List(); int index = 1; @@ -228,9 +229,18 @@ namespace IRaCIS.Core.Application.Helper //有实际的文件 if (mappings.Count > 0) - { + { // 保存 DICOMDIR 到临时文件 不能直接写入到流种 - await dicomDir.SaveAsync(dirSavePath); + + if (dirSavePath.IsNotNullOrEmpty()) + { + await dicomDir.SaveAsync(dirSavePath); + + } + else + { + await dicomDir.SaveAsync(outputStream); + } } } diff --git a/IRaCIS.Core.Application/Helper/OSSService.cs b/IRaCIS.Core.Application/Helper/OSSService.cs index 417b9b5b4..685bcb318 100644 --- a/IRaCIS.Core.Application/Helper/OSSService.cs +++ b/IRaCIS.Core.Application/Helper/OSSService.cs @@ -220,7 +220,7 @@ public class OSSService(IOptionsMonitor options, public object result { get; private set; } - + private static readonly object _tokenLock = new(); /// /// 将指定前缀下的所有现有文件立即转为目标存储类型 @@ -934,32 +934,52 @@ public class OSSService(IOptionsMonitor options, //后端批量上传 或者下载,不每个文件获取临时token private void BackBatchGetToken() { + + + // 过期时间 ≤ 当前时间 + 15分钟 时需要续期 + if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS") { - if (AliyunOSSTempToken == null) + if (AliyunOSSTempToken != null && AliyunOSSTempToken.Expiration > DateTime.Now.AddMinutes(15)) { - GetObjectStoreTempToken(); - } - //token 过期了 - if (AliyunOSSTempToken?.Expiration.AddSeconds(10) <= DateTime.Now) - { - GetObjectStoreTempToken(); + return; // 还有15分钟以上,不需要续期 } + lock (_tokenLock) + { + if (AliyunOSSTempToken == null || + AliyunOSSTempToken.Expiration <= DateTime.Now.AddMinutes(15)) + { + GetObjectStoreTempToken(); + + Log.Logger.Warning("后端获取阿里云临时 Token"); + } + } } else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS") { - if (AWSTempToken == null) + + + if (AWSTempToken != null && AWSTempToken.Expiration > DateTime.Now.AddMinutes(15)) { - GetObjectStoreTempToken(); + return; } - //token 过期了 - if (AWSTempToken.Expiration?.AddSeconds(10) <= DateTime.Now) + + lock (_tokenLock) { - GetObjectStoreTempToken(); + if (AWSTempToken == null || + AWSTempToken.Expiration <= DateTime.Now.AddMinutes(15)) + { + GetObjectStoreTempToken(); + + Log.Logger.Warning("后端获取s3 临时 Token"); + } } + } + + } diff --git a/IRaCIS.Core.Application/Service/Common/TrialImageDownloadService.cs b/IRaCIS.Core.Application/Service/Common/TrialImageDownloadService.cs index 6ba580e20..5bf9183b6 100644 --- a/IRaCIS.Core.Application/Service/Common/TrialImageDownloadService.cs +++ b/IRaCIS.Core.Application/Service/Common/TrialImageDownloadService.cs @@ -1,4 +1,5 @@ using Aliyun.OSS; +using CommunityToolkit.HighPerformance; using DocumentFormat.OpenXml.EMMA; using DocumentFormat.OpenXml.Office.CustomUI; using DocumentFormat.OpenXml.Office2010.Excel; @@ -20,6 +21,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using MiniExcelLibs; +using NPOI.Util; using Org.BouncyCastle.Utilities.Zlib; using SharpCompress.Common; using System; @@ -60,6 +62,14 @@ namespace IRaCIS.Core.Application.Service { try { + + #region 方式一 有的必须在内存中,不能用这种 + //await using var source = await sourceFactory(); + //// 如果你是从 stream 打开 + //var dicomFile = await DicomFile.OpenAsync(source); + #endregion + + #region 方式二 await using var source = await sourceFactory(); // 【关键修复】将 OSS 流缓冲到 MemoryStream @@ -79,6 +89,8 @@ namespace IRaCIS.Core.Application.Service // 如果你是从 stream 打开 var dicomFile = await DicomFile.OpenAsync(source.CanSeek ? source : bufferedStream); + #endregion + //获取像素是否为封装形式 var syntax = dicomFile.Dataset.InternalTransferSyntax; @@ -120,11 +132,393 @@ namespace IRaCIS.Core.Application.Service } + #region zip 流方式 直接下载 + + + public sealed class ZipItem + { + public string ZipEntryPath { get; set; } = ""; + + public string? OssPath { get; set; } + + public bool IsEncapsulated { get; set; } + + public Func? CustomWriter { get; set; } + } + + + private async Task CreateVisitZipAsync(string zipPath, List zipItems) + { + Directory.CreateDirectory(Path.GetDirectoryName(zipPath)!); + + await using var zipFileStream = new FileStream(zipPath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4 * 1024 * 1024, useAsync: true); + + using var archive = new ZipArchive(zipFileStream, ZipArchiveMode.Create, leaveOpen: false); + + foreach (var item in zipItems) + { + var entry = archive.CreateEntry(item.ZipEntryPath.Replace("\\", "/"), CompressionLevel.NoCompression); + + await using var entryStream = entry.Open(); + + if (item.CustomWriter != null) + { + await item.CustomWriter(entryStream); + continue; + } + + if (string.IsNullOrWhiteSpace(item.OssPath)) + continue; + + if (item.IsEncapsulated) + { + var success = await TryWriteMergedDicomAsync(() => _oSSService.GetStreamFromOSSAsync(item.OssPath), entryStream); + + if (!success) + { + Log.Logger.Warning($"合并多帧失败:{item.ZipEntryPath} ossPath: {item.OssPath}"); + + throw new Exception($"合并多帧失败-终止当前zip包:{item.ZipEntryPath} ossPath: {item.OssPath}"); + } + + } + else + { + await using var ossStream = await _oSSService.GetStreamFromOSSAsync(item.OssPath); + + await ossStream.CopyToAsync(entryStream, 4 * 1024 * 1024); + } + + + } + } + + //查询一个访视 + // ↓ + //生成 DICOMDIR + // ↓ + //创建 ZipArchive + // ↓ + //OSS流直接写 ZipEntry + // ↓ + //完成一个访视.zip + // ↓ + //记录日志 + // ↓ + //处理下一个访视 + + [HttpPost] + [AllowAnonymous] + public async Task DownloadExcelTrialImageZIPStream(Guid trialId) + { + var trialInfo = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo }).FirstOrDefault(); + + #region 设置目录 + + var rootFolder = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); + Directory.CreateDirectory(rootFolder); + + // 获取无效字符(系统定义的) + string invalidChars = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars()); + + // 用正则表达式替换所有非法字符为下划线或空字符 + string pattern = $"[{Regex.Escape(invalidChars)}]"; + + var regexNo = Regex.Replace(trialInfo.ResearchProgramNo, pattern, "_"); + + // 创建一个临时文件夹来存放文件 + string trialFolderPath = Path.Combine(rootFolder, $"{regexNo}");//_{NewId.NextGuid()} + Directory.CreateDirectory(trialFolderPath); + + #endregion + + var oldVisits = MiniExcel.Query(Path.Combine(rootFolder, "Old.xlsx")).ToList(); + + var downloadVisits = MiniExcel.Query(Path.Combine(rootFolder, "download.xlsx")).ToList().Where(t => t.SubjectCode.IsNotNullOrEmpty() && t.VisitName.IsNotNullOrEmpty()).ToList(); + + downloadVisits = downloadVisits.Where(t => !oldVisits.Any(old => old.VisitNum == t.VisitNum && old.SubjectCode == t.SubjectCode && old.VisitName.Trim().ToLower() == t.VisitName.Trim().ToLower())).ToList(); + + var visitIndex = 0; + var skipCount = 0; + foreach (var downloadVisit in downloadVisits) + { + var downloadInfo = _trialRepository.Where(t => t.Id == trialId).Select(t => new + { + t.ResearchProgramNo, + t.TrialCode, + + VisitList = t.SubjectVisitList.Where(t => t.VisitName.Trim() == downloadVisit.VisitName.Trim() && t.Subject.Code.Trim() == downloadVisit.SubjectCode.Trim() && t.VisitNum == downloadVisit.VisitNum) + .Select(sv => new + { + SubjectVisitId = sv.Id, + TrialSiteCode = sv.TrialSite.TrialSiteCode, + SubjectCode = sv.Subject.Code, + VisitName = sv.VisitName, + VisitNum = sv.VisitNum, + StudyList = sv.StudyList.Select(u => new + { + StudyId = u.Id, + u.PatientId, + u.StudyTime, + u.StudyCode, + u.StudyInstanceUid, + u.StudyDIRPath, + + SeriesList = u.SeriesList.Where(t => t.IsReading).Select(z => new + { + z.Modality, + + InstancePathList = z.DicomInstanceList.Where(t => t.IsReading).Select(k => new + { + InstanceId = k.Id, + k.Path, + k.IsEncapsulated, + k.NumberOfFrames, + }).ToList() + }) + + }).ToList(), + + NoneDicomStudyList = sv.NoneDicomStudyList.Where(t => t.IsReading).Select(nd => new + { + nd.Modality, + nd.StudyCode, + nd.ImageDate, + + FileList = nd.NoneDicomFileList.Where(t => t.IsReading).Select(file => new + { + file.FileName, + file.Path, + file.FileType + }).ToList() + }).ToList() + }).OrderBy(t => t.SubjectCode).ThenBy(t => t.VisitNum).ToList() + + }).FirstOrDefault(); + + if (downloadInfo == null) + { + continue; + } + + #region 排除已经下载的 + + var logFilePath = Path.Combine(rootFolder, $"{trialId}_{regexNo}_download_log.csv"); + + if (File.Exists(logFilePath)) + { + var existVisits = MiniExcel.Query(logFilePath, configuration: new MiniExcelLibs.Csv.CsvConfiguration() + { + StreamReaderFunc = (stream) => new StreamReader(stream, Encoding.GetEncoding("gb2312")) + }).ToList(); + + if (existVisits.Any(old => old.VisitNum == downloadVisit.VisitNum && old.SubjectCode == downloadVisit.SubjectCode && old.VisitName.Trim().ToLower() == downloadVisit.VisitName.Trim().ToLower())) + { + Log.Logger.Warning($"[{visitIndex}] Excel显示已下载,跳过当前访视:{downloadVisit.SubjectCode} {downloadVisit.VisitName} {downloadVisit.VisitNum}"); + skipCount++; + continue; + } + + } + + + #endregion + + foreach (var visitItem in downloadInfo.VisitList) + { + if (visitItem.StudyList.Count() == 0 && visitItem.NoneDicomStudyList.Count() == 0) + { + Log.Logger.Warning($"[{visitIndex}]查询无检查,跳过当前访视:{downloadVisit.SubjectCode} {downloadVisit.VisitName} {downloadVisit.VisitNum}"); + skipCount++; + continue; + } + + try + { + #region 导出访视 + + var zipItems = new List(); + + var visitFolderName = $"{visitItem.SubjectCode}_{visitItem.VisitName.Trim()}"; + + #region DICOM + + foreach (var studyInfo in visitItem.StudyList) + { + var dirDic = new Dictionary(); + + var studyFolderName = $"{studyInfo.StudyCode}_{studyInfo.StudyTime:yyyy-MM-dd}_{string.Join('_', studyInfo.SeriesList.Select(t => t.Modality))}"; + + #region DICOMDIR + + + if (!_instanceRepository.Where(t => t.IsReading && t.DicomSerie.IsReading) + .Where(t => visitItem.SubjectVisitId == t.SubjectVisitId).Any(c => c.TransferSytaxUID == string.Empty)) + { + var list = _subjectVisitRepository.Where(t => t.Id == visitItem.SubjectVisitId).SelectMany(t => t.StudyList) + .SelectMany(t => t.InstanceList.Where(t => t.IsReading && t.DicomSerie.IsReading && t.StudyId == studyInfo.StudyId)) + .Select(t => new StudyDIRInfo() + { + + DicomStudyId = t.DicomStudy.Id, + + PatientId = downloadInfo.TrialCode + "-" + t.DicomStudy.Subject.Code, + PatientName = t.DicomStudy.PatientName, + PatientBirthDate = t.DicomStudy.PatientBirthDate, + PatientSex = t.DicomStudy.PatientSex, + + StudyInstanceUid = t.StudyInstanceUid, + StudyId = t.DicomStudy.StudyId, + DicomStudyDate = t.DicomStudy.DicomStudyDate, + DicomStudyTime = t.DicomStudy.DicomStudyTime, + AccessionNumber = t.DicomStudy.AccessionNumber, + + StudyDescription = t.DicomStudy.Description, + + SeriesInstanceUid = t.DicomSerie.SeriesInstanceUid, + Modality = t.DicomSerie.Modality, + DicomSeriesDate = t.DicomSerie.DicomSeriesDate, + DicomSeriesTime = t.DicomSerie.DicomSeriesTime, + SeriesNumber = t.DicomSerie.SeriesNumber, + SeriesDescription = t.DicomSerie.Description, + + InstanceId = t.Id, + SopInstanceUid = t.SopInstanceUid, + SOPClassUID = t.SOPClassUID, + InstanceNumber = t.InstanceNumber, + MediaStorageSOPClassUID = t.MediaStorageSOPClassUID, + MediaStorageSOPInstanceUID = t.MediaStorageSOPInstanceUID, + TransferSytaxUID = t.TransferSytaxUID, + + }).ToList(); + + foreach (var group in list.GroupBy(t => new { t.StudyInstanceUid, t.DicomStudyId })) + { + + using var ms = new MemoryStream(); + + await DicomDIRHelper.GenerateStudyDIR(group.ToList(), dirDic, outputStream: ms); + + var dicomDirBytes = ms.ToArray(); + + zipItems.Add(new ZipItem + { + ZipEntryPath = $"{visitFolderName}/{studyFolderName}/DICOMDIR", + + CustomWriter = async entryStream => + { + await entryStream.WriteAsync(dicomDirBytes); + } + }); + } + + } + + + #endregion + + + + + foreach (var seriesInfo in studyInfo.SeriesList) + { + foreach (var instanceInfo in seriesInfo.InstancePathList) + { + zipItems.Add(new ZipItem + { + OssPath = instanceInfo.Path, + + IsEncapsulated = instanceInfo.IsEncapsulated, + + ZipEntryPath = $"{visitFolderName}/" + $"{studyFolderName}/" + $"IMAGE/" + $"{dirDic[instanceInfo.InstanceId.ToString()]}" + }); + } + } + + + + } + + #endregion + + + #region NoneDicom + + foreach (var study in visitItem.NoneDicomStudyList) + { + var studyFolderName = $"{study.StudyCode}_" + $"{study.ImageDate:yyyy-MM-dd}_" + $"{study.Modality}"; + + foreach (var file in study.FileList) + { + zipItems.Add(new ZipItem + { + OssPath = HttpUtility.UrlDecode(file.Path), + + ZipEntryPath = $"{visitFolderName}/" + $"{studyFolderName}/" + $"{Path.GetFileName(file.FileName)}" + }); + } + } + + #endregion + + + #region zip + + + var zipPath = Path.Combine(trialFolderPath, visitFolderName + ".zip"); + + Log.Logger.Warning($"[{visitIndex}] {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}开始打包下载访视:{visitFolderName}"); + + try + { + await CreateVisitZipAsync(zipPath, zipItems); + + //Log.Logger.Warning($"zip exists={File.Exists(zipPath)} size={new FileInfo(zipPath).Length}"); + + Log.Logger.Warning($"[{visitIndex}] {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}访视打包下载完成:{visitFolderName}"); + + DownloadLogger.Write(logFilePath, visitItem.SubjectCode, visitItem.VisitNum, visitItem.VisitName, "Success"); + + } + catch (Exception ex) + { + Log.Logger.Warning($"出现异常{ex}删除压缩包:{visitFolderName}"); + //如果有异常,删除失败的压缩包 + if (File.Exists(zipPath)) + { + File.Delete(zipPath); + } + + } + + + #endregion + + + + #endregion + + } + + catch (Exception ex) + { + Log.Logger.Error(ex, $"导出失败:{downloadVisit.SubjectCode} {downloadVisit.VisitName} {downloadVisit.VisitNum}"); + } + + + } + } + + return ResponseOutput.Ok(); + } + + #endregion + + + #region Excel 下载 先下载,然后再压缩,删除方式 public static class DownloadLogger { - - public static void Write( string logFilePath, string subjectCode, @@ -132,27 +526,34 @@ namespace IRaCIS.Core.Application.Service 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); + // 首次创建时写入 BOM + if (!fileExists) + { + var bom = new UTF8Encoding(true).GetPreamble(); + stream.Write(bom, 0, bom.Length); + } + using var writer = new StreamWriter(stream, new UTF8Encoding(false)); - // 首次写入表头 + // 写入表头 if (!fileExists) { writer.WriteLine("Time,SubjectCode,VisitNum,VisitName,Message"); } + // 写入数据 string line = string.Join(",", [ - Escape(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), + Escape(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), subjectCode, visitNum, visitName, @@ -162,14 +563,12 @@ namespace IRaCIS.Core.Application.Service writer.WriteLine(line); } - // 防止逗号、换行导致 CSV 错乱 private static string Escape(string? value) { if (string.IsNullOrEmpty(value)) return ""; value = value.Replace("\"", "\"\""); - return $"\"{value}\""; } } @@ -211,13 +610,20 @@ namespace IRaCIS.Core.Application.Service #endregion + var oldVisits = MiniExcel.Query(Path.Combine(rootFolder, "Old.xlsx")).ToList(); - var downloadVisits = MiniExcel.Query(Path.Combine(rootFolder, "download.xlsx")).ToList().Where(t => t.SubjectCode.IsNotNullOrEmpty() && t.VisitName.IsNotNullOrEmpty()); + var downloadVisits = MiniExcel.Query(Path.Combine(rootFolder, "download.xlsx")).ToList().Where(t => t.SubjectCode.IsNotNullOrEmpty() && t.VisitName.IsNotNullOrEmpty()).ToList(); + + downloadVisits = downloadVisits.Where(t => !oldVisits.Any(old => old.VisitNum == t.VisitNum && old.SubjectCode == t.SubjectCode && + old.VisitName.Trim().ToLower() == t.VisitName.Trim().ToLower())).ToList(); var downloadJobs = new List(); + var skipCount = 0; + var visitIndex = 0; foreach (var downloadVisit in downloadVisits) { + visitIndex++; var downloadInfo = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, @@ -291,6 +697,8 @@ namespace IRaCIS.Core.Application.Service if (existVisits.Any(old => old.VisitNum == downloadVisit.VisitNum && old.SubjectCode == downloadVisit.SubjectCode && old.VisitName.Trim().ToLower() == downloadVisit.VisitName.Trim().ToLower())) { + Log.Logger.Warning($"[{visitIndex}] Excel显示已下载,跳过当前访视:{downloadVisit.SubjectCode} {downloadVisit.VisitName} {downloadVisit.VisitNum}"); + skipCount++; continue; } @@ -305,9 +713,12 @@ namespace IRaCIS.Core.Application.Service { if (visitItem.StudyList.Count() == 0 && visitItem.NoneDicomStudyList.Count() == 0) { + Log.Logger.Warning($"[{visitIndex}]查询无检查,跳过当前访视:{downloadVisit.SubjectCode} {downloadVisit.VisitName} {downloadVisit.VisitNum}"); + skipCount++; continue; } + Log.Logger.Warning($"[{visitIndex}]开始获取访视信息准备下载任务:{visitItem.SubjectCode} {visitItem.VisitName} {visitItem.VisitNum}"); foreach (var studyInfo in visitItem.StudyList) { @@ -457,6 +868,8 @@ namespace IRaCIS.Core.Application.Service //建立压缩包 string visitFolderPath = Path.Combine(trialFolderPath, $"{visitItem.SubjectCode}_{visitItem.VisitName.Trim()}"); + var currentIndex = visitIndex; + downloadJobs.Add(new DownloadJob() { Name = $"{visitItem.SubjectCode}_{visitItem.VisitName.Trim()}_Zip", @@ -465,7 +878,7 @@ namespace IRaCIS.Core.Application.Service Action = async () => { - Log.Logger.Warning($" {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}压缩访视:{visitItem.SubjectCode} {visitItem.VisitName} {visitItem.VisitNum}"); + Log.Logger.Warning($"[{currentIndex}] {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}开启另外线程压缩访视:{visitItem.SubjectCode} {visitItem.VisitName} {visitItem.VisitNum}"); string zipPath = visitFolderPath + ".zip"; @@ -502,6 +915,7 @@ namespace IRaCIS.Core.Application.Service return Task.CompletedTask; } }); + } @@ -515,14 +929,14 @@ namespace IRaCIS.Core.Application.Service - + Log.Logger.Warning($"{downloadVisits.Count}个访视信息核对准备完毕, 跳过{skipCount} 个,后端开始下载任务......"); #region 异步方式处理 int totalCount = downloadJobs.Count; int downloadedCount = 0; - Log.Logger.Warning($"开始下载总数: {totalCount}"); + Log.Logger.Warning($"下载文件总数: {totalCount}"); foreach (var job in downloadJobs) { try @@ -975,6 +1389,8 @@ namespace IRaCIS.Core.Application.Service } + #endregion + /// /// 下载影像 维护dir信息 并回传到OSS diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs index 70458f08a..cb899be04 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs @@ -82,9 +82,35 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc { try { + #region 方式一 有的必须在内存中,不能用这种 + //await using var source = await sourceFactory(); + //// 如果你是从 stream 打开 + //var dicomFile = await DicomFile.OpenAsync(source); + #endregion + + #region 方式二 + await using var source = await sourceFactory(); + + // 【关键修复】将 OSS 流缓冲到 MemoryStream + using var bufferedStream = new MemoryStream(); + + if (source.CanSeek) + { + source.Position = 0; + + } + else + { + // 完全复制到内存流 + await source.CopyToAsync(bufferedStream); + bufferedStream.Position = 0; // 重置位置 + } + // 如果你是从 stream 打开 - var dicomFile = await DicomFile.OpenAsync(source); + var dicomFile = await DicomFile.OpenAsync(source.CanSeek ? source : bufferedStream); + + #endregion //获取像素是否为封装形式 var syntax = dicomFile.Dataset.InternalTransferSyntax; diff --git a/IRaCIS.Core.Application/TestService.cs b/IRaCIS.Core.Application/TestService.cs index 34e6f3364..83ca9053e 100644 --- a/IRaCIS.Core.Application/TestService.cs +++ b/IRaCIS.Core.Application/TestService.cs @@ -1,30 +1,17 @@ using Aliyun.OSS; -using DocumentFormat.OpenXml.Spreadsheet; using FellowOakDicom; using FellowOakDicom.Imaging; using IRaCIS.Application.Contracts; -using IRaCIS.Core.Application.BusinessFilter; using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Helper; -using IRaCIS.Core.Application.Helper.OtherTool; -using IRaCIS.Core.Application.Service.BusinessFilter; using IRaCIS.Core.Application.ViewModel; -using IRaCIS.Core.Domain; -using IRaCIS.Core.Domain.Models; -using IRaCIS.Core.Domain.Share; -using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Infra.EFCore.Context; using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure.Encryption; using IRaCIS.Core.Infrastructure.NewtonsoftJson; using MassTransit; -using MassTransit.Caching.Internals; -using MassTransit.Mediator; -using MathNet.Numerics; -using MaxMind.GeoIP2; using Medallion.Threading; using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -32,25 +19,15 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using MiniExcelLibs; -using Minio.DataModel; using Newtonsoft.Json; -using NPOI.SS.Formula.Functions; using NPOI.XWPF.UserModel; -using SharpCompress.Common; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Processing; -using System.Collections.Concurrent; using System.ComponentModel.DataAnnotations; -using System.Diagnostics; -using System.Globalization; -using System.IO; using System.Linq.Dynamic.Core; -using System.Reactive.Subjects; -using System.Reflection.Metadata.Ecma335; using System.Runtime.InteropServices; using System.Text; -using static IRaCIS.Core.Domain.Share.StaticData;