修改访视下载bug
continuous-integration/drone/push Build is passing Details

Test_HIR_Net8
hang 2025-12-17 17:42:05 +08:00
parent 345189995e
commit bd9d1a6298
4 changed files with 139 additions and 5 deletions

View File

@ -944,11 +944,11 @@ namespace IRaCIS.Core.API.Controllers
var progress = new
{
CountPercent = totalCount > 0
? Math.Round(receivedCount * 100m / totalCount, 2).ToString()
? Math.Round(receivedCount * 100m / totalCount, 2).ToString()
: "0",
SizePercent = totalSize > 0
? Math.Round(receivedSize * 100m / totalSize, 2).ToString()
SizePercent = totalSize > 0
? Math.Round(receivedSize * 100m / totalSize, 2).ToString()
: "0",
Speed = (speedBps / 1024 >= 1024
@ -972,6 +972,9 @@ namespace IRaCIS.Core.API.Controllers
try
{
//开始推送一次
await NotifyProgressAsync(true);
await using var responseStream = Response.BodyWriter.AsStream();
using var zip = new ZipArchive(responseStream, ZipArchiveMode.Create, leaveOpen: true);
@ -1090,7 +1093,7 @@ namespace IRaCIS.Core.API.Controllers
var trialInfo = _trialRepository.Where(t => t.Id == inCommand.TrialId).Select(t => new { t.TrialCode, t.ResearchProgramNo }).FirstOrDefault();
var trialZipName = $"{trialInfo.TrialCode}_{trialInfo.ResearchProgramNo}_Image_";
var trialZipName = $"{trialInfo.TrialCode}_{trialInfo.ResearchProgramNo}_Image_";
long receivedSize = 0;
long receivedCount = 0;
@ -1159,6 +1162,9 @@ namespace IRaCIS.Core.API.Controllers
try
{
//开始推送一次
await NotifyProgressAsync(true);
await using var responseStream = Response.BodyWriter.AsStream();
using var zip = new ZipArchive(responseStream, ZipArchiveMode.Create, leaveOpen: true);
@ -1262,6 +1268,125 @@ namespace IRaCIS.Core.API.Controllers
}
[HttpPost("download/ClinicalDataDownload")]
public async Task<IActionResult> ClinicalDataDownload([FromServices] IReadingClinicalDataService _readingClinicalDataService, [FromServices] IOSSService _oSSService,
[FromServices] IHubContext<DownloadHub, IDownloadClient> _downLoadHub,
[FromServices] IRepository<ReadingQuestionCriterionTrial> _trialReadingCriterionRepository,
ClinicalDataDownloadDTO inCommand)
{
var dataList = await _readingClinicalDataService.GetTrialClinicalDataSelect(inCommand);
var trialInfo = _trialReadingCriterionRepository.Where(t => t.Id == inCommand.TrialReadingCriterionId).Select(t => new { t.Trial.TrialCode, t.Trial.ResearchProgramNo, t.CriterionName }).FirstOrDefault();
var trialZipName = $"{trialInfo.TrialCode}_{trialInfo.ResearchProgramNo}_{trialInfo.CriterionName}_template_";
long receivedCount = 0;
long totalCount = dataList.Count;
var abortToken = HttpContext.RequestAborted;
// -------- SignalR 节流参数 --------
var notifyInterval = TimeSpan.FromSeconds(1);
var lastNotify = DateTime.UtcNow;
// 用于计算下载速度
DateTime lastSpeedCheck = DateTime.UtcNow;
async Task NotifyProgressAsync(bool force = false)
{
var now = DateTime.UtcNow;
var elapsedSeconds = (now - lastSpeedCheck).TotalSeconds;
// 如果没有强制推送,并且未到推送间隔,则返回
if (!force && elapsedSeconds < notifyInterval.TotalSeconds)
return;
lastSpeedCheck = now;
lastNotify = DateTime.UtcNow;
var progress = new
{
CountPercent = totalCount > 0
? Math.Round(receivedCount * 100m / totalCount, 2).ToString()
: "0",
};
// 不阻塞下载流程
_ = _downLoadHub.Clients
.User(_userInfo.IdentityUserId.ToString())
.ReceivProgressAsync(
inCommand.CurrentNoticeId,
progress
);
}
Response.ContentType = "application/zip";
Response.Headers["Content-Disposition"] = $"attachment; filename={trialZipName}{ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId)}.zip";
Response.Headers["Cache-Control"] = "no-store";
try
{
//开始推送一次
await NotifyProgressAsync(true);
await using var responseStream = Response.BodyWriter.AsStream();
using var zip = new ZipArchive(responseStream, ZipArchiveMode.Create, leaveOpen: true);
foreach (var data in dataList)
{
abortToken.ThrowIfCancellationRequested();
//当前完成大小
receivedCount++;
var entryPath =$"{data.FileName}";
var entry = zip.CreateEntry(entryPath, CompressionLevel.Fastest);
await using var entryStream = entry.Open();
await using var source = await _oSSService.GetStreamFromOSSAsync(data.Path);
await source.CopyToAsync(entryStream, 32 * 1024, abortToken);
await NotifyProgressAsync();
}
// 正常完成
await NotifyProgressAsync(true);
}
catch (OperationCanceledException)
{
// ✅ 客户端取消 / 断开 —— 正常情况
Log.Logger.Warning("Download canceled by client");
}
catch (IOException ex) when (abortToken.IsCancellationRequested)
{
// ✅ HttpClient 流在中断时的常见异常
Log.Logger.Warning($"Client disconnected: {ex.Message}");
}
catch (NullReferenceException ex) when (abortToken.IsCancellationRequested)
{
// ✅ HttpConnection.ContentLengthReadStream 已知问题
Log.Logger.Warning($"Stream aborted: {ex.Message}");
}
return new EmptyResult();
}
}
}

View File

@ -31,5 +31,7 @@ namespace IRaCIS.Core.Application.Contracts
Task<IResponseOutput> SignConsistencyAnalysisReadingClinicalData(SignConsistencyAnalysisReadingClinicalDataInDto inDto);
Task<List<GetTrialClinicalDataSelectOutDto>> GetTrialClinicalDataSelect(GetTrialClinicalDataSelectIndto inDto);
}
}

View File

@ -1,4 +1,5 @@
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure.Extention;
@ -965,6 +966,12 @@ namespace IRaCIS.Application.Contracts
}
public class ClinicalDataDownloadDTO: GetTrialClinicalDataSelectIndto
{
[NotDefault]
public string CurrentNoticeId { get; set; }
}
public class VisitImageDownloadCommand
{
public Guid TrialId { get; set; }

View File

@ -3598,7 +3598,7 @@ namespace IRaCIS.Application.Services
await _subejctVisitDownloadRepository.AddAsync(preDownloadInfo, true);
return ResponseOutput.Ok(visitList, preDownloadInfo.Id);
return ResponseOutput.Ok(visitList, preDownloadInfo);
}
/// <summary>