将dicom文件内处理拆成单方法,减缓内存占用测试
continuous-integration/drone/push Build is passing Details

Test_HIR_Net8
hang 2026-01-04 14:33:26 +08:00
parent 72d7136f1c
commit 88ded12f37
1 changed files with 168 additions and 89 deletions

View File

@ -1,4 +1,5 @@
using AutoMapper;
using DocumentFormat.OpenXml.Bibliography;
using DocumentFormat.OpenXml.ExtendedProperties;
using ExcelDataReader;
using FellowOakDicom;
@ -50,6 +51,7 @@ using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Path = System.IO.Path;
@ -941,9 +943,9 @@ namespace IRaCIS.Core.API.Controllers
[HttpGet("download/GetPatientStudyBatchDownload")]
public async Task<IActionResult> GetDownloadPatientStudyBatch( [FromServices] IOSSService _oSSService,
public async Task<IActionResult> GetDownloadPatientStudyBatch([FromServices] IOSSService _oSSService,
[FromServices] IHubContext<DownloadHub, IDownloadClient> _downLoadHub,
//[FromServices] IPatientService _patientService,
//[FromServices] IPatientService _patientService,
[FromServices] IServiceScopeFactory _serviceScopeFactory,
[FromQuery] PatientImageDownloadCommand inCommand)
{
@ -958,7 +960,7 @@ namespace IRaCIS.Core.API.Controllers
return (result.Data, (SubejctVisitDownload)result.OtherData);
}
});
long receivedSize = 0;
long receivedCount = 0;
long totalSize = downloadInfo.ImageSize;
@ -1091,67 +1093,79 @@ namespace IRaCIS.Core.API.Controllers
if (instance.IsEncapsulated)
{
#region 将多帧合并为一帧
#region 将多帧合并为一帧-在方法里,占用内存,拆成单独方法,不占用内存
try
{
// 如果你是从 stream 打开
var dicomFile = await DicomFile.OpenAsync(source);
//try
//{
// // 如果你是从 stream 打开
// var dicomFile = await DicomFile.OpenAsync(source);
//获取像素是否为封装形式
var syntax = dicomFile.Dataset.InternalTransferSyntax;
// //获取像素是否为封装形式
// var syntax = dicomFile.Dataset.InternalTransferSyntax;
//对于封装像素的文件做转换
if (syntax.IsEncapsulated)
{
// 获取 Pixel Data 标签
var pixelData = DicomPixelData.Create(dicomFile.Dataset);
// //对于封装像素的文件做转换
// if (syntax.IsEncapsulated)
// {
// // 获取 Pixel Data 标签
// var pixelData = DicomPixelData.Create(dicomFile.Dataset);
// 创建一个新的片段序列
var newFragments = new DicomOtherByteFragment(DicomTag.PixelData);
// 获取每帧数据并封装为单独的片段
for (int n = 0; n < pixelData.NumberOfFrames; n++)
{
var frameData = pixelData.GetFrame(n);
newFragments.Fragments.Add(new MemoryByteBuffer(frameData.Data));
}
// // 创建一个新的片段序列
// var newFragments = new DicomOtherByteFragment(DicomTag.PixelData);
// // 获取每帧数据并封装为单独的片段
// for (int n = 0; n < pixelData.NumberOfFrames; n++)
// {
// var frameData = pixelData.GetFrame(n);
// newFragments.Fragments.Add(new MemoryByteBuffer(frameData.Data));
// }
var frag = dicomFile.Dataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData);
// var frag = dicomFile.Dataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData);
var originOffsetTable = frag?.OffsetTable;
// var originOffsetTable = frag?.OffsetTable;
newFragments.OffsetTable.AddRange(originOffsetTable?.ToArray());
// 替换原有的片段序列
dicomFile.Dataset.AddOrUpdate(newFragments);
}
// newFragments.OffsetTable.AddRange(originOffsetTable?.ToArray());
// // 替换原有的片段序列
// dicomFile.Dataset.AddOrUpdate(newFragments);
// }
await dicomFile.SaveAsync(entryStream);
// await dicomFile.SaveAsync(entryStream);
}
catch (Exception ex)
{
//}
//catch (Exception ex)
//{
Log.Logger.Warning($"处理多帧合并{instance.Path}失败,以原始文件下载: {ex.Message}");
// Log.Logger.Warning($"处理多帧合并{instance.Path}失败,以原始文件下载: {ex.Message}");
try
{
await using var source2 = await _oSSService.GetStreamFromOSSAsync(instance.Path);
// try
// {
// await using var source2 = await _oSSService.GetStreamFromOSSAsync(instance.Path);
await source2.CopyToAsync(entryStream, 32 * 1024, abortToken);
}
catch (Exception ex2)
{
// await source2.CopyToAsync(entryStream, 32 * 1024, abortToken);
// }
// catch (Exception ex2)
// {
Log.Logger.Warning($"原始文件下载{instance.Path}失败: {ex2.Message}");
}
}
// Log.Logger.Warning($"原始文件下载{instance.Path}失败: {ex2.Message}");
// }
//}
#endregion
var ok = await TryWriteMergedDicomAsync(
() => _oSSService.GetStreamFromOSSAsync(instance.Path),
entryStream
);
if (!ok)
{
await using var source2 = await _oSSService.GetStreamFromOSSAsync(instance.Path);
await source2.CopyToAsync(entryStream, 32 * 1024, abortToken);
}
}
else
{
@ -1216,6 +1230,55 @@ namespace IRaCIS.Core.API.Controllers
}
private static async Task<bool> TryWriteMergedDicomAsync(
Func<Task<Stream>> sourceFactory,
Stream output)
{
try
{
await using var source = await sourceFactory();
// 如果你是从 stream 打开
var dicomFile = await DicomFile.OpenAsync(source);
//获取像素是否为封装形式
var syntax = dicomFile.Dataset.InternalTransferSyntax;
//对于封装像素的文件做转换
if (syntax.IsEncapsulated)
{
// 获取 Pixel Data 标签
var pixelData = DicomPixelData.Create(dicomFile.Dataset);
// 创建一个新的片段序列
var newFragments = new DicomOtherByteFragment(DicomTag.PixelData);
// 获取每帧数据并封装为单独的片段
for (int n = 0; n < pixelData.NumberOfFrames; n++)
{
var frameData = pixelData.GetFrame(n);
newFragments.Fragments.Add(new MemoryByteBuffer(frameData.Data));
}
var frag = dicomFile.Dataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData);
var originOffsetTable = frag?.OffsetTable;
newFragments.OffsetTable.AddRange(originOffsetTable?.ToArray());
// 替换原有的片段序列
dicomFile.Dataset.AddOrUpdate(newFragments);
}
await dicomFile.SaveAsync(output);
return true;
}
catch (Exception ex)
{
// 只记录,不传播
Log.Logger.Warning($"TryWriteMergedDicomAsync failed: {ex.Message}");
return false;
}
}
[HttpPost("download/PatientStudyBatchDownloadForm")]
public async Task<IActionResult> DownloadPatientStudyBatchForm([FromServices] IPatientService _patientService, [FromServices] IOSSService _oSSService,
@ -1883,10 +1946,10 @@ namespace IRaCIS.Core.API.Controllers
[HttpGet("download/VisitImageDownload")]
public async Task<IActionResult> VisitImageDownload( [FromServices] IOSSService _oSSService,
public async Task<IActionResult> VisitImageDownload([FromServices] IOSSService _oSSService,
[FromServices] IHubContext<DownloadHub, IDownloadClient> _downLoadHub,
//[FromServices] IRepository<Trial> _trialRepository,
//[FromServices] IPatientService _patientService,
//[FromServices] IRepository<Trial> _trialRepository,
//[FromServices] IPatientService _patientService,
[FromServices] IServiceScopeFactory _serviceScopeFactory, // 注入ServiceScopeFactory
[FromQuery] VisitImageDownloadCommand inCommand)
{
@ -2044,61 +2107,77 @@ namespace IRaCIS.Core.API.Controllers
if (instance.IsEncapsulated)
{
#region 将多帧合并为一帧
try
{
// 如果你是从 stream 打开
var dicomFile = await DicomFile.OpenAsync(source);
#region 将多帧合并为一帧-在方法里,占用内存,拆成单独方法,不占用内存
//获取像素是否为封装形式
var syntax = dicomFile.Dataset.InternalTransferSyntax;
//对于封装像素的文件做转换
if (syntax.IsEncapsulated)
{
// 获取 Pixel Data 标签
var pixelData = DicomPixelData.Create(dicomFile.Dataset);
// 创建一个新的片段序列
var newFragments = new DicomOtherByteFragment(DicomTag.PixelData);
// 获取每帧数据并封装为单独的片段
for (int n = 0; n < pixelData.NumberOfFrames; n++)
{
var frameData = pixelData.GetFrame(n);
newFragments.Fragments.Add(new MemoryByteBuffer(frameData.Data));
}
//try
//{
// // 如果你是从 stream 打开
// var dicomFile = await DicomFile.OpenAsync(source);
var frag = dicomFile.Dataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData);
// //获取像素是否为封装形式
// var syntax = dicomFile.Dataset.InternalTransferSyntax;
var originOffsetTable = frag?.OffsetTable;
// //对于封装像素的文件做转换
// if (syntax.IsEncapsulated)
// {
// // 获取 Pixel Data 标签
// var pixelData = DicomPixelData.Create(dicomFile.Dataset);
newFragments.OffsetTable.AddRange(originOffsetTable?.ToArray());
// 替换原有的片段序列
dicomFile.Dataset.AddOrUpdate(newFragments);
}
// // 创建一个新的片段序列
// var newFragments = new DicomOtherByteFragment(DicomTag.PixelData);
// // 获取每帧数据并封装为单独的片段
// for (int n = 0; n < pixelData.NumberOfFrames; n++)
// {
// var frameData = pixelData.GetFrame(n);
// newFragments.Fragments.Add(new MemoryByteBuffer(frameData.Data));
// }
await dicomFile.SaveAsync(entryStream);
// var frag = dicomFile.Dataset.GetDicomItem<DicomOtherByteFragment>(DicomTag.PixelData);
}
catch (Exception ex)
{
// var originOffsetTable = frag?.OffsetTable;
Log.Logger.Warning($"处理多帧合并{instance.Path}失败: {ex.Message}");
// newFragments.OffsetTable.AddRange(originOffsetTable?.ToArray());
// // 替换原有的片段序列
// dicomFile.Dataset.AddOrUpdate(newFragments);
// }
try
{
await using var source2 = await _oSSService.GetStreamFromOSSAsync(instance.Path);
// await dicomFile.SaveAsync(entryStream);
await source2.CopyToAsync(entryStream, 32 * 1024, abortToken);
}
catch (Exception ex2)
{
//}
//catch (Exception ex)
//{
Log.Logger.Warning($"原始文件下载{instance.Path}失败: {ex2.Message}");
}
}
// Log.Logger.Warning($"处理多帧合并{instance.Path}失败,以原始文件下载: {ex.Message}");
// try
// {
// await using var source2 = await _oSSService.GetStreamFromOSSAsync(instance.Path);
// await source2.CopyToAsync(entryStream, 32 * 1024, abortToken);
// }
// catch (Exception ex2)
// {
// Log.Logger.Warning($"原始文件下载{instance.Path}失败: {ex2.Message}");
// }
//}
#endregion
var ok = await TryWriteMergedDicomAsync(
() => _oSSService.GetStreamFromOSSAsync(instance.Path),
entryStream
);
if (!ok)
{
await using var source2 = await _oSSService.GetStreamFromOSSAsync(instance.Path);
await source2.CopyToAsync(entryStream, 32 * 1024, abortToken);
}
}
else
{