修改访视下载bug
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
345189995e
commit
bd9d1a6298
|
|
@ -972,6 +972,9 @@ namespace IRaCIS.Core.API.Controllers
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
//开始推送一次
|
||||||
|
await NotifyProgressAsync(true);
|
||||||
|
|
||||||
await using var responseStream = Response.BodyWriter.AsStream();
|
await using var responseStream = Response.BodyWriter.AsStream();
|
||||||
using var zip = new ZipArchive(responseStream, ZipArchiveMode.Create, leaveOpen: true);
|
using var zip = new ZipArchive(responseStream, ZipArchiveMode.Create, leaveOpen: true);
|
||||||
|
|
||||||
|
|
@ -1159,6 +1162,9 @@ namespace IRaCIS.Core.API.Controllers
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
//开始推送一次
|
||||||
|
await NotifyProgressAsync(true);
|
||||||
|
|
||||||
await using var responseStream = Response.BodyWriter.AsStream();
|
await using var responseStream = Response.BodyWriter.AsStream();
|
||||||
using var zip = new ZipArchive(responseStream, ZipArchiveMode.Create, leaveOpen: true);
|
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();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,5 +31,7 @@ namespace IRaCIS.Core.Application.Contracts
|
||||||
|
|
||||||
Task<IResponseOutput> SignConsistencyAnalysisReadingClinicalData(SignConsistencyAnalysisReadingClinicalDataInDto inDto);
|
Task<IResponseOutput> SignConsistencyAnalysisReadingClinicalData(SignConsistencyAnalysisReadingClinicalDataInDto inDto);
|
||||||
|
|
||||||
|
Task<List<GetTrialClinicalDataSelectOutDto>> GetTrialClinicalDataSelect(GetTrialClinicalDataSelectIndto inDto);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
|
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
|
||||||
|
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||||
using IRaCIS.Core.Application.ViewModel;
|
using IRaCIS.Core.Application.ViewModel;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using IRaCIS.Core.Infrastructure.Extention;
|
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 class VisitImageDownloadCommand
|
||||||
{
|
{
|
||||||
public Guid TrialId { get; set; }
|
public Guid TrialId { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -3598,7 +3598,7 @@ namespace IRaCIS.Application.Services
|
||||||
|
|
||||||
await _subejctVisitDownloadRepository.AddAsync(preDownloadInfo, true);
|
await _subejctVisitDownloadRepository.AddAsync(preDownloadInfo, true);
|
||||||
|
|
||||||
return ResponseOutput.Ok(visitList, preDownloadInfo.Id);
|
return ResponseOutput.Ok(visitList, preDownloadInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue