zip 流方式demo
continuous-integration/drone/push Build is failing Details

Test_IRC_Net8^2
hang 2026-06-04 13:08:37 +08:00
parent 73fa62e6a2
commit d719015fa2
2 changed files with 62 additions and 49 deletions

View File

@ -1,4 +1,5 @@
using Aliyun.OSS;
using CommunityToolkit.HighPerformance;
using DocumentFormat.OpenXml.EMMA;
using DocumentFormat.OpenXml.Office.CustomUI;
using DocumentFormat.OpenXml.Office2010.Excel;
@ -148,11 +149,9 @@ namespace IRaCIS.Core.Application.Service
private async Task CreateVisitZipAsync(string zipPath, List<ZipItem> zipItems)
{
Directory.CreateDirectory(
Path.GetDirectoryName(zipPath)!);
Directory.CreateDirectory(Path.GetDirectoryName(zipPath)!);
await using var zipFileStream =
new FileStream(zipPath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4 * 1024 * 1024, useAsync: true);
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);
@ -177,7 +176,9 @@ namespace IRaCIS.Core.Application.Service
if (!success)
{
Log.Logger.Warning($"合并多帧失败:{item.ZipEntryPath}");
Log.Logger.Warning($"合并多帧失败:{item.ZipEntryPath} ossPath: {item.OssPath}");
throw new Exception($"合并多帧失败-终止当前zip包{item.ZipEntryPath} ossPath: {item.OssPath}");
}
}
@ -235,8 +236,7 @@ namespace IRaCIS.Core.Application.Service
var downloadVisits = MiniExcel.Query<SubjectVisitExcel>(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();
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;
@ -298,7 +298,7 @@ namespace IRaCIS.Core.Application.Service
if (downloadInfo == null)
{
return ResponseOutput.Ok();
continue;
}
#region 排除已经下载的
@ -312,8 +312,7 @@ namespace IRaCIS.Core.Application.Service
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()))
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++;
@ -342,6 +341,8 @@ namespace IRaCIS.Core.Application.Service
var visitFolderName = $"{visitItem.SubjectCode}_{visitItem.VisitName.Trim()}";
#region DICOM
foreach (var studyInfo in visitItem.StudyList)
{
var dirDic = new Dictionary<string, string>();
@ -394,6 +395,11 @@ namespace IRaCIS.Core.Application.Service
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
{
@ -401,7 +407,7 @@ namespace IRaCIS.Core.Application.Service
CustomWriter = async entryStream =>
{
await DicomDIRHelper.GenerateStudyDIR(group.ToList(), dirDic, outputStream: entryStream);
await entryStream.WriteAsync(dicomDirBytes);
}
});
}
@ -412,7 +418,7 @@ namespace IRaCIS.Core.Application.Service
#endregion
#region DICOM
foreach (var seriesInfo in studyInfo.SeriesList)
{
@ -429,11 +435,13 @@ namespace IRaCIS.Core.Application.Service
}
}
#endregion
}
#endregion
#region NoneDicom
foreach (var study in visitItem.NoneDicomStudyList)
@ -453,15 +461,40 @@ namespace IRaCIS.Core.Application.Service
#endregion
var zipPath = Path.Combine(rootFolder, visitFolderName + ".zip");
Log.Logger.Warning($"开始压缩访视:{visitFolderName}");
#region zip
await CreateVisitZipAsync(zipPath, zipItems);
DownloadLogger.Write(logFilePath, visitItem.SubjectCode, visitItem.VisitNum, visitItem.VisitName, "Success");
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
Log.Logger.Warning($"访视压缩完成:{visitFolderName}");
#endregion
@ -486,8 +519,6 @@ namespace IRaCIS.Core.Application.Service
public static class DownloadLogger
{
public static void Write(
string logFilePath,
string subjectCode,
@ -495,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,
@ -525,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}\"";
}
}

View File

@ -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;