功能修改
continuous-integration/drone/push Build is passing Details

Test_HIR_Net8
he 2026-05-27 11:15:53 +08:00
parent 8801308002
commit 4f83944a30
5 changed files with 183 additions and 23 deletions

View File

@ -1285,26 +1285,134 @@ namespace IRaCIS.Core.API.Controllers
}
}
///// <summary>
///// 下载阅片报告和图片
///// </summary>
///// <param name="_readingImageTaskService"></param>
///// <param name="_oSSService"></param>
///// <param name="_downLoadHub"></param>
///// <param name="inCommand"></param>
///// <returns></returns>
//[HttpPost("download/ReadingReportAndImage")]
//public async Task<IActionResult> DownloadReadingReportAndImage([FromServices] IReadingImageTaskService _readingImageTaskService, [FromServices] IOSSService _oSSService,
// [FromServices] IHubContext<DownloadHub, IDownloadClient> _downLoadHub,
// [FromForm] GetReadingReportAndImageInDto inCommand)
//{
// Response.ContentType = "application/zip";
// Response.Headers["Content-Disposition"] = $"attachment; filename=Image_{ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId)}.zip";
// Response.Headers["Cache-Control"] = "no-store";
/// <summary>
/// 下载阅片报告和图片
/// </summary>
/// <param name="_readingImageTaskService"></param>
/// <param name="_oSSService"></param>
/// <param name="_downLoadHub"></param>
/// <param name="inCommand"></param>
/// <returns></returns>
[HttpPost("download/ReadingReportAndImage")]
public async Task<IActionResult> DownloadReadingReportAndImage([FromServices] IReadingImageTaskService _readingImageTaskService, [FromServices] IOSSService _oSSService,
[FromServices] IHubContext<DownloadHub, IDownloadClient> _downLoadHub,
[FromForm] GetReadingReportAndImageInDto inCommand)
{
Response.ContentType = "application/zip";
Response.Headers["Content-Disposition"] = $"attachment; filename=Image_{ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId)}.zip";
Response.Headers["Cache-Control"] = "no-store";
// var data = await _readingImageTaskService.GetReadingReportAndImage(inCommand);
var data = await _readingImageTaskService.GetReadingReportAndImage(inCommand);
var abortToken = HttpContext.RequestAborted;
//}
string SanitizePathSegment(string? value, string defaultValue)
{
var result = string.IsNullOrWhiteSpace(value) ? defaultValue : value.Trim();
foreach (var invalidChar in Path.GetInvalidFileNameChars())
{
result = result.Replace(invalidChar, '_');
}
return string.IsNullOrWhiteSpace(result) ? defaultValue : result;
}
string GetEntryFileName(string? sourcePath, string defaultPrefix, int index)
{
var fileName = Path.GetFileName(sourcePath ?? string.Empty);
if (string.IsNullOrWhiteSpace(fileName))
{
fileName = $"{defaultPrefix}_{index}";
}
fileName = SanitizePathSegment(fileName, $"{defaultPrefix}_{index}");
return fileName;
}
string BuildUniqueEntryPath(HashSet<string> existingEntryPaths, string folderPath, string fileName)
{
var extension = Path.GetExtension(fileName);
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
var candidatePath = $"{folderPath}/{fileName}";
var suffix = 1;
while (!existingEntryPaths.Add(candidatePath))
{
candidatePath = $"{folderPath}/{fileNameWithoutExtension}_{suffix}{extension}";
suffix++;
}
return candidatePath;
}
try
{
await using var responseStream = Response.BodyWriter.AsStream();
using var zip = new ZipArchive(responseStream, ZipArchiveMode.Create, leaveOpen: true);
var existingEntryPaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var item in data)
{
abortToken.ThrowIfCancellationRequested();
var folderName =
$"{SanitizePathSegment(item.SubjectCode, "UnknownSubject")}_{SanitizePathSegment(item.VisitName, "UnknownVisit")}";
foreach (var reportUrl in item.ReportUrlList.Where(x => !string.IsNullOrWhiteSpace(x)))
{
abortToken.ThrowIfCancellationRequested();
try
{
var fileName = GetEntryFileName(reportUrl, "Report", existingEntryPaths.Count + 1);
var entryPath = BuildUniqueEntryPath(existingEntryPaths, folderName, fileName);
var entry = zip.CreateEntry(entryPath, CompressionLevel.Fastest);
await using var entryStream = entry.Open();
await using var source = await _oSSService.GetStreamFromOSSAsync(reportUrl);
await source.CopyToAsync(entryStream, 32 * 1024, abortToken);
}
catch (Exception ex)
{
Log.Logger.Warning($"处理阅片报告文件{reportUrl}失败: {ex.Message}");
}
}
foreach (var imageUrl in item.ImageUrlList.Where(x => !string.IsNullOrWhiteSpace(x)))
{
abortToken.ThrowIfCancellationRequested();
try
{
var fileName = GetEntryFileName(imageUrl, "Image", existingEntryPaths.Count + 1);
var entryPath = BuildUniqueEntryPath(existingEntryPaths, folderName, fileName);
var entry = zip.CreateEntry(entryPath, CompressionLevel.Fastest);
await using var entryStream = entry.Open();
await using var source = await _oSSService.GetStreamFromOSSAsync(imageUrl);
await source.CopyToAsync(entryStream, 32 * 1024, abortToken);
}
catch (Exception ex)
{
Log.Logger.Warning($"处理阅片图片文件{imageUrl}失败: {ex.Message}");
}
}
}
}
catch (OperationCanceledException)
{
Log.Logger.Warning("Download reading report and image canceled by client");
}
catch (IOException ex) when (abortToken.IsCancellationRequested)
{
Log.Logger.Warning($"Client disconnected: {ex.Message}");
}
catch (NullReferenceException ex) when (abortToken.IsCancellationRequested)
{
Log.Logger.Warning($"Stream aborted: {ex.Message}");
}
return new EmptyResult();
}
[HttpPost("download/PatientStudyBatchDownloadForm")]
public async Task<IActionResult> DownloadPatientStudyBatchForm([FromServices] IPatientService _patientService, [FromServices] IOSSService _oSSService,

View File

@ -337,6 +337,16 @@
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.API.Controllers.UploadDownLoadController.DownloadReadingReportAndImage(IRaCIS.Core.Application.Contracts.IReadingImageTaskService,IRaCIS.Core.Application.Helper.IOSSService,Microsoft.AspNetCore.SignalR.IHubContext{IRaCIS.Core.API.DownloadHub,IRaCIS.Core.API.IDownloadClient},IRaCIS.Core.Application.Service.Reading.Dto.GetReadingReportAndImageInDto)">
<summary>
下载阅片报告和图片
</summary>
<param name="_readingImageTaskService"></param>
<param name="_oSSService"></param>
<param name="_downLoadHub"></param>
<param name="inCommand"></param>
<returns></returns>
</member>
<member name="T:IRaCIS.Core.API.IpPolicyRateLimitSetup">
<summary>
IPLimit限流 启动服务

View File

@ -7817,6 +7817,26 @@
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.ReadingReportAndImage.SubjectCode">
<summary>
受试者编号
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.ReadingReportAndImage.VisitName">
<summary>
访视名称
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.ReadingReportAndImage.ReportUrlList">
<summary>
报告文件的URL地址列表
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.ReadingReportAndImage.ImageUrlList">
<summary>
图片的URl地址列表
</summary>
</member>
<member name="P:IRaCIS.Core.Application.Service.Reading.Dto.DownLoadReadReportInDto.VisitTaskId">
<summary>
任务Id
@ -12902,6 +12922,13 @@
IR影像阅片
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.GetReadingReportAndImage(IRaCIS.Core.Application.Service.Reading.Dto.GetReadingReportAndImageInDto)">
<summary>
获取阅片报告数据和图像
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.GetTNMValue(IRaCIS.Core.Application.Service.Reading.Dto.TNMValueDto)">
<summary>
获取TNMValue
@ -14951,17 +14978,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">

View File

@ -300,12 +300,24 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
public class ReadingReportAndImage
{
/// <summary>
/// 受试者编号
/// </summary>
public string SubjectCode { get; set; }
/// <summary>
/// 访视名称
/// </summary>
public string VisitName { get; set; }
/// <summary>
/// 报告文件的URL地址列表
/// </summary>
public List<string> ReportUrlList { get; set; } = new List<string>();
/// <summary>
/// 图片的URl地址列表
/// </summary>
public List<string> ImageUrlList { get; set; } = new List<string>();
}

View File

@ -92,8 +92,11 @@ namespace IRaCIS.Core.Application.Service
}
else
{
taskList = await _visitTaskRepository.Where(x => x.TrialReadingCriterionId==inDto.TrialCriterionId&&x.TaskState== TaskState.Effect && x.ReadingTaskState == ReadingTaskState.HaveSigned && x.ReadingCategory == ReadingCategory.Visit)
.Include(x => x.LesionList).Include(x => x.Subject).Include(x => x.SourceSubjectVisit).ToListAsync();
taskList = await _visitTaskRepository.Where(x => x.TrialReadingCriterionId==inDto.TrialCriterionId && x.ReadingCategory == ReadingCategory.Visit && x.TaskState== TaskState.Effect && x.ReadingTaskState == ReadingTaskState.HaveSigned && x.ReadingCategory == ReadingCategory.Visit)
.Include(x => x.LesionList)
.Include(x => x.Subject)
.Include(x => x.SourceSubjectVisit)
.ToListAsync();
}
List< ReadingReportAndImage > result = new List<ReadingReportAndImage>() { };