504 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			504 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C#
		
	
	
| using FellowOakDicom.Network;
 | ||
| using FellowOakDicom;
 | ||
| using System;
 | ||
| using System.Collections.Generic;
 | ||
| using System.Linq;
 | ||
| using System.Text;
 | ||
| using System.Threading.Tasks;
 | ||
| using Microsoft.Extensions.Logging;
 | ||
| using Microsoft.Extensions.DependencyInjection;
 | ||
| using Microsoft.Extensions.Hosting;
 | ||
| using IRaCIS.Core.SCP.Service;
 | ||
| using IRaCIS.Core.Domain.Models;
 | ||
| using IRaCIS.Core.Infra.EFCore;
 | ||
| using Medallion.Threading;
 | ||
| using IRaCIS.Core.Domain.Share;
 | ||
| using Serilog;
 | ||
| using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
 | ||
| using Microsoft.Extensions.Options;
 | ||
| using System.Data;
 | ||
| using FellowOakDicom.Imaging;
 | ||
| using SharpCompress.Common;
 | ||
| using SixLabors.ImageSharp.Formats.Jpeg;
 | ||
| using IRaCIS.Core.Infrastructure;
 | ||
| using IRaCIS.Core.Infrastructure.Extention;
 | ||
| using FellowOakDicom.IO.Buffer;
 | ||
| 
 | ||
| namespace IRaCIS.Core.SCP.Service
 | ||
| {
 | ||
| 
 | ||
|     public class DicomSCPServiceOption
 | ||
|     {
 | ||
|         public List<string> CalledAEList { get; set; }
 | ||
| 
 | ||
|         public string ServerPort { get; set; }
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|     public class CStoreSCPService : DicomService, IDicomServiceProvider, IDicomCStoreProvider, IDicomCEchoProvider
 | ||
|     {
 | ||
|         private IServiceProvider _serviceProvider { get; set; }
 | ||
| 
 | ||
|         private List<Guid> _SCPStudyIdList => _ImageUploadList.Where(t => t.SCPStudyId != Guid.Empty).Select(t => t.SCPStudyId).ToList();
 | ||
| 
 | ||
|         private List<ImageUploadInfo> _ImageUploadList { get; set; } = new List<ImageUploadInfo>();
 | ||
| 
 | ||
|         private SCPImageUpload _upload { get; set; }
 | ||
| 
 | ||
|         private Guid _trialId { get; set; }
 | ||
| 
 | ||
|         private Guid _trialSiteId { get; set; }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         private static readonly DicomTransferSyntax[] _acceptedTransferSyntaxes = new DicomTransferSyntax[]
 | ||
|         {
 | ||
|                DicomTransferSyntax.ExplicitVRLittleEndian,
 | ||
|                DicomTransferSyntax.ExplicitVRBigEndian,
 | ||
|                DicomTransferSyntax.ImplicitVRLittleEndian
 | ||
|         };
 | ||
| 
 | ||
|         private static readonly DicomTransferSyntax[] _acceptedImageTransferSyntaxes = new DicomTransferSyntax[]
 | ||
|         {
 | ||
|                 // Lossless
 | ||
|                DicomTransferSyntax.JPEGLSLossless,   //1.2.840.10008.1.2.4.80
 | ||
|                DicomTransferSyntax.JPEG2000Lossless, //1.2.840.10008.1.2.4.90
 | ||
|                DicomTransferSyntax.JPEGProcess14SV1, //1.2.840.10008.1.2.4.70
 | ||
|                DicomTransferSyntax.JPEGProcess14,    //1.2.840.10008.1.2.4.57 JPEG Lossless, Non-Hierarchical (Process 14)
 | ||
|                DicomTransferSyntax.RLELossless,      //1.2.840.10008.1.2.5
 | ||
|                // Lossy
 | ||
|                DicomTransferSyntax.JPEGLSNearLossless,//1.2.840.10008.1.2.4.81"
 | ||
|                DicomTransferSyntax.JPEG2000Lossy,     //1.2.840.10008.1.2.4.91
 | ||
|                DicomTransferSyntax.JPEGProcess1,      //1.2.840.10008.1.2.4.50
 | ||
|                DicomTransferSyntax.JPEGProcess2_4,    //1.2.840.10008.1.2.4.51
 | ||
|                // Uncompressed
 | ||
|                DicomTransferSyntax.ExplicitVRLittleEndian, //1.2.840.10008.1.2.1
 | ||
|                DicomTransferSyntax.ExplicitVRBigEndian,    //1.2.840.10008.1.2.2
 | ||
|                DicomTransferSyntax.ImplicitVRLittleEndian  //1.2.840.10008.1.2
 | ||
|         };
 | ||
| 
 | ||
| 
 | ||
|         public CStoreSCPService(INetworkStream stream, Encoding fallbackEncoding, Microsoft.Extensions.Logging.ILogger log, DicomServiceDependencies dependencies, IServiceProvider injectServiceProvider)
 | ||
|             : base(stream, fallbackEncoding, log, dependencies)
 | ||
|         {
 | ||
|             _serviceProvider = injectServiceProvider.CreateScope().ServiceProvider;
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         public Task OnReceiveAssociationRequestAsync(DicomAssociation association)
 | ||
|         {
 | ||
| 
 | ||
|             _upload = new SCPImageUpload() { StartTime = DateTime.Now, CallingAE = association.CallingAE, CalledAE = association.CalledAE, CallingAEIP = association.RemoteHost };
 | ||
| 
 | ||
| 
 | ||
|             Log.Logger.Warning($"接收到来自{association.CallingAE}的连接");
 | ||
| 
 | ||
|             //_serviceProvider = (IServiceProvider)this.UserState;
 | ||
| 
 | ||
|             var _trialDicomAERepository = _serviceProvider.GetService<IRepository<TrialDicomAE>>();
 | ||
| 
 | ||
| 
 | ||
|             var trialDicomAEList = _trialDicomAERepository.Select(t => new { t.CalledAE, t.TrialId }).ToList();
 | ||
|             var trialCalledAEList = trialDicomAEList.Select(t => t.CalledAE).ToList();
 | ||
| 
 | ||
|             Log.Logger.Information("当前系统配置:", string.Join('|', trialDicomAEList));
 | ||
| 
 | ||
|             var findCalledAE = trialDicomAEList.Where(t => t.CalledAE == association.CalledAE).FirstOrDefault();
 | ||
| 
 | ||
|             var isCanReceiveIamge = false;
 | ||
| 
 | ||
|             if (findCalledAE != null)
 | ||
|             {
 | ||
|                 _trialId = findCalledAE.TrialId;
 | ||
| 
 | ||
|                 var _trialSiteDicomAERepository = _serviceProvider.GetService<IRepository<TrialSiteDicomAE>>();
 | ||
| 
 | ||
| 
 | ||
|                 var findTrialSiteAE = _trialSiteDicomAERepository.Where(t => t.CallingAE == association.CallingAE && t.TrialId==_trialId).FirstOrDefault();
 | ||
| 
 | ||
|                 if (findTrialSiteAE != null)
 | ||
|                 {
 | ||
|                     _trialSiteId = findTrialSiteAE.TrialSiteId;
 | ||
| 
 | ||
|                     isCanReceiveIamge = true;
 | ||
|                 }
 | ||
| 
 | ||
|                
 | ||
|             }
 | ||
| 
 | ||
|             if (association.CallingAE == "test-callingAE")
 | ||
|             {
 | ||
|                 isCanReceiveIamge = true;
 | ||
|             }
 | ||
| 
 | ||
|             if (!trialCalledAEList.Contains(association.CalledAE) || isCanReceiveIamge == false)
 | ||
|             {
 | ||
| 
 | ||
|                 Log.Logger.Warning($"拒绝CallingAE:{association.CallingAE}  CalledAE:{association.CalledAE}的连接");
 | ||
| 
 | ||
|                 return SendAssociationRejectAsync(
 | ||
|                     DicomRejectResult.Permanent,
 | ||
|                     DicomRejectSource.ServiceUser,
 | ||
|                     DicomRejectReason.CalledAENotRecognized);
 | ||
|             }
 | ||
| 
 | ||
|             foreach (var pc in association.PresentationContexts)
 | ||
|             {
 | ||
|                 if (pc.AbstractSyntax == DicomUID.Verification)
 | ||
|                 {
 | ||
|                     pc.AcceptTransferSyntaxes(_acceptedTransferSyntaxes);
 | ||
|                 }
 | ||
|                 else if (pc.AbstractSyntax.StorageCategory != DicomStorageCategory.None)
 | ||
|                 {
 | ||
|                     pc.AcceptTransferSyntaxes(_acceptedImageTransferSyntaxes);
 | ||
|                 }
 | ||
|             }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|             return SendAssociationAcceptAsync(association);
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         public async Task OnReceiveAssociationReleaseRequestAsync()
 | ||
|         {
 | ||
|             var _distributedLockProvider = _serviceProvider.GetService<IDistributedLockProvider>();
 | ||
| 
 | ||
|             var @lock = _distributedLockProvider.CreateLock($"{_upload.CallingAE}");
 | ||
| 
 | ||
|             using (await @lock.AcquireAsync())
 | ||
|             {
 | ||
| 
 | ||
|                 await DataMaintenanceAsaync();
 | ||
| 
 | ||
|                 //记录监控
 | ||
| 
 | ||
|                 await AddUploadLogAsync();
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|                 var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
 | ||
|                 //将检查设置为传输结束
 | ||
|                 await _studyRepository.BatchUpdateNoTrackingAsync(t => _SCPStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true });
 | ||
| 
 | ||
|                 await _studyRepository.SaveChangesAndClearAllTrackingAsync();
 | ||
| 
 | ||
|             }
 | ||
| 
 | ||
|             await SendAssociationReleaseResponseAsync();
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
|         private async Task AddUploadLogAsync()
 | ||
|         {
 | ||
|             //记录监控
 | ||
| 
 | ||
|             var _SCPImageUploadRepository = _serviceProvider.GetService<IRepository<SCPImageUpload>>();
 | ||
| 
 | ||
|             _upload.EndTime = DateTime.Now;
 | ||
|             _upload.StudyCount = _ImageUploadList.Count;
 | ||
|             _upload.TrialId = _trialId;
 | ||
|             _upload.TrialSiteId = _trialSiteId;
 | ||
| 
 | ||
|             _upload.UploadJsonStr = (new SCPImageLog() { UploadList = _ImageUploadList }).ToJsonStr();
 | ||
| 
 | ||
|             //可能是测试echo 导致记录了
 | ||
|             await _SCPImageUploadRepository.AddAsync(_upload, _upload.FileCount > 0 ? true : false);
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         private async Task DataMaintenanceAsaync()
 | ||
|         {
 | ||
|             Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}传输结束:开始维护数据,处理检查Modality");
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|             //处理检查Modality
 | ||
|             var _dictionaryRepository = _serviceProvider.GetService<IRepository<Dictionary>>();
 | ||
|             var _seriesRepository = _serviceProvider.GetService<IRepository<SCPSeries>>();
 | ||
|             var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
 | ||
| 
 | ||
|             var dicModalityList = _dictionaryRepository.Where(t => t.Code == "Modality").SelectMany(t => t.ChildList.Select(c => c.Value)).ToList();
 | ||
|             var seriesModalityList = _seriesRepository.Where(t => _SCPStudyIdList.Contains(t.StudyId)).Select(t => new { SCPStudyId = t.StudyId, t.Modality }).ToList();
 | ||
| 
 | ||
|             foreach (var g in seriesModalityList.GroupBy(t => t.SCPStudyId))
 | ||
|             {
 | ||
|                 var modality = string.Join('、', g.Select(t => t.Modality).Distinct().ToList());
 | ||
| 
 | ||
|                 //特殊逻辑
 | ||
|                 var modalityForEdit = dicModalityList.Contains(modality) ? modality : String.Empty;
 | ||
| 
 | ||
|                 if (modality == "MR")
 | ||
|                 {
 | ||
|                     modalityForEdit = "MRI";
 | ||
|                 }
 | ||
| 
 | ||
|                 if (modality == "PT")
 | ||
|                 {
 | ||
|                     modalityForEdit = "PET";
 | ||
|                 }
 | ||
|                 if (modality == "PT、CT" || modality == "CT、PT")
 | ||
|                 {
 | ||
|                     modalityForEdit = "PET-CT";
 | ||
|                 }
 | ||
| 
 | ||
|                 await _studyRepository.BatchUpdateNoTrackingAsync(t => t.Id == g.Key, u => new SCPStudy() { Modalities = modality, ModalityForEdit = modalityForEdit });
 | ||
| 
 | ||
|             }
 | ||
| 
 | ||
|             Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}维护数据结束");
 | ||
|         }
 | ||
| 
 | ||
|         public void OnReceiveAbort(DicomAbortSource source, DicomAbortReason reason)
 | ||
|         {
 | ||
|             Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}接收中断,中断原因:{source.ToString() + reason.ToString()}");
 | ||
|             /* nothing to do here */
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         public async void OnConnectionClosed(Exception exception)
 | ||
|         {
 | ||
|             /* nothing to do here */
 | ||
| 
 | ||
|             //奇怪的bug  上传的时候,用王捷修改的影像,会关闭,重新连接,导致检查id 丢失,然后状态不一致
 | ||
|             if (exception == null)
 | ||
|             {
 | ||
|                 //var _studyRepository = _serviceProvider.GetService<IRepository<SCPStudy>>();
 | ||
|                 ////将检查设置为传输结束
 | ||
|                 //await _studyRepository.BatchUpdateNoTrackingAsync(t => _SCPStudyIdList.Contains(t.Id), u => new SCPStudy() { IsUploadFinished = true });
 | ||
| 
 | ||
|                 //await _studyRepository.SaveChangesAndClearAllTrackingAsync();
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 //记录日志
 | ||
|                 await AddUploadLogAsync();
 | ||
|             }
 | ||
| 
 | ||
|             Log.Logger.Warning($"连接关闭 {exception?.Message} {exception?.InnerException?.Message}");
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         public async Task<DicomCStoreResponse> OnCStoreRequestAsync(DicomCStoreRequest request)
 | ||
|         {
 | ||
| 
 | ||
|             string studyInstanceUid = request.Dataset.GetSingleValueOrDefault(DicomTag.StudyInstanceUID, string.Empty);
 | ||
|             string seriesInstanceUid = request.Dataset.GetSingleValueOrDefault(DicomTag.SeriesInstanceUID, string.Empty);
 | ||
|             string sopInstanceUid = request.Dataset.GetSingleValueOrDefault(DicomTag.SOPInstanceUID, string.Empty);
 | ||
|             string patientIdStr = request.Dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty);
 | ||
| 
 | ||
|             if (studyInstanceUid.IsNullOrEmpty() || seriesInstanceUid.IsNullOrEmpty() || sopInstanceUid.IsNullOrEmpty())
 | ||
|             {
 | ||
|                 Log.Logger.Error($"接收数据读取StudyInstanceUID:{studyInstanceUid}、SeriesInstanceUID:{seriesInstanceUid}、SOPInstanceUID:{sopInstanceUid}有空 ");
 | ||
| 
 | ||
|                 return new DicomCStoreResponse(request, DicomStatus.Success);
 | ||
|             }
 | ||
| 
 | ||
|             //确保来了影像集合存在
 | ||
|             if (!_ImageUploadList.Any(t => t.StudyInstanceUid == studyInstanceUid))
 | ||
|             {
 | ||
|                 _ImageUploadList.Add(new ImageUploadInfo() { StudyInstanceUid = studyInstanceUid });
 | ||
|             }
 | ||
| 
 | ||
|             //Guid studyId = IdentifierHelper.CreateGuid(studyInstanceUid, trialId.ToString());
 | ||
|             Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, _trialId.ToString());
 | ||
|             Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid, _trialId.ToString());
 | ||
| 
 | ||
| 
 | ||
|             var ossService = _serviceProvider.GetService<IOSSService>();
 | ||
|             var dicomArchiveService = _serviceProvider.GetService<IDicomArchiveService>();
 | ||
|             var _seriesRepository = _serviceProvider.GetService<IRepository<SCPSeries>>();
 | ||
| 
 | ||
|             var _distributedLockProvider = _serviceProvider.GetService<IDistributedLockProvider>();
 | ||
| 
 | ||
|             var storeRelativePath = string.Empty;
 | ||
|             var ossFolderPath = $"{_trialId}/Image/PACS/{_trialSiteId}/{studyInstanceUid}";
 | ||
| 
 | ||
| 
 | ||
|             long fileSize = 0;
 | ||
|             try
 | ||
|             {
 | ||
|                 using (MemoryStream ms = new MemoryStream())
 | ||
|                 {
 | ||
|                     await request.File.SaveAsync(ms);
 | ||
| 
 | ||
|                     #region 1帧拆成多个固定大小的,方便移动端浏览
 | ||
| 
 | ||
|                     // 回到开头,读取 dicom
 | ||
|                     ms.Position = 0;
 | ||
|                     var dicomFile = DicomFile.Open(ms);
 | ||
| 
 | ||
|                     var pixelData = DicomPixelData.Create(dicomFile.Dataset);
 | ||
|                     var syntax = pixelData.Syntax;
 | ||
| 
 | ||
|                     // 每个 fragment 固定大小 (64KB 示例,可以自己调整)
 | ||
|                     int fragmentSize = 20 * 1024;
 | ||
| 
 | ||
|                     if (syntax.IsEncapsulated)
 | ||
|                     {
 | ||
|                         var newFragments = new DicomOtherByteFragment(DicomTag.PixelData);
 | ||
| 
 | ||
|                         for (int n = 0; n < pixelData.NumberOfFrames; n++)
 | ||
|                         {
 | ||
|                             var frameData = pixelData.GetFrame(n); // 获取完整一帧
 | ||
|                             var data = frameData.Data;
 | ||
|                             int offset = 0;
 | ||
| 
 | ||
|                             while (offset < data.Length)
 | ||
|                             {
 | ||
|                                 int size = Math.Min(fragmentSize, data.Length - offset);
 | ||
|                                 var buffer = new byte[size];
 | ||
|                                 Buffer.BlockCopy(data, offset, buffer, 0, size);
 | ||
| 
 | ||
|                                 newFragments.Fragments.Add(new MemoryByteBuffer(buffer));
 | ||
|                                 offset += size;
 | ||
|                             }
 | ||
|                         }
 | ||
| 
 | ||
|                         // 替换原 PixelData
 | ||
|                         dicomFile.Dataset.AddOrUpdate(newFragments);
 | ||
| 
 | ||
| 
 | ||
|                         // 重新保存 dicom 到流
 | ||
|                         ms.SetLength(0);
 | ||
|                         dicomFile.Save(ms);
 | ||
|                     }
 | ||
| 
 | ||
| 
 | ||
|                     ms.Position = 0;
 | ||
| 
 | ||
|                     #endregion
 | ||
| 
 | ||
| 
 | ||
|                     #region 本地测试
 | ||
|                     //// --- 保存到本地文件测试 ---
 | ||
|                     //var localPath = @"D:\TestDicom.dcm";
 | ||
|                     //using (var fs = new FileStream(localPath, FileMode.Create, FileAccess.Write))
 | ||
|                     //{
 | ||
|                     //    ms.CopyTo(fs);
 | ||
|                     //}
 | ||
|                     //return new DicomCStoreResponse(request, DicomStatus.Success);
 | ||
| 
 | ||
|                     #endregion
 | ||
| 
 | ||
| 
 | ||
|                     //irc 从路径最后一截取Guid
 | ||
|                     storeRelativePath = await ossService.UploadToOSSAsync(ms, ossFolderPath, instanceId.ToString(), false);
 | ||
| 
 | ||
|                     fileSize = ms.Length;
 | ||
|                 }
 | ||
| 
 | ||
|                 Log.Logger.Information($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} {request.SOPInstanceUID} 上传完成 ");
 | ||
| 
 | ||
|             }
 | ||
|             catch (Exception ec)
 | ||
|             {
 | ||
|                 Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} 上传异常 {ec.Message}");
 | ||
|             }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|             var @lock = _distributedLockProvider.CreateLock($"{studyInstanceUid}");
 | ||
| 
 | ||
|             using (await @lock.AcquireAsync())
 | ||
|             {
 | ||
|                 try
 | ||
|                 {
 | ||
|                     var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(request.File, _trialId, _trialSiteId, storeRelativePath, Association.CallingAE, Association.CalledAE,fileSize);
 | ||
| 
 | ||
| 
 | ||
|                     var series = await _seriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
 | ||
| 
 | ||
|                     //没有缩略图
 | ||
|                     if (series != null && string.IsNullOrEmpty(series.ImageResizePath))
 | ||
|                     {
 | ||
| 
 | ||
|                         // 生成缩略图
 | ||
|                         using (var memoryStream = new MemoryStream())
 | ||
|                         {
 | ||
|                             DicomImage image = new DicomImage(request.Dataset);
 | ||
| 
 | ||
|                             var sharpimage = image.RenderImage().AsSharpImage();
 | ||
|                             sharpimage.Save(memoryStream, new JpegEncoder());
 | ||
| 
 | ||
|                             // 上传缩略图到 OSS
 | ||
| 
 | ||
|                             var seriesPath = await ossService.UploadToOSSAsync(memoryStream, ossFolderPath, seriesId.ToString() + ".preview.jpg", false);
 | ||
| 
 | ||
|                             Console.WriteLine(seriesPath + "  Id:  " + seriesId);
 | ||
| 
 | ||
|                             series.ImageResizePath = seriesPath;
 | ||
| 
 | ||
|                         }
 | ||
|                     }
 | ||
| 
 | ||
| 
 | ||
|                     await _seriesRepository.SaveChangesAsync();
 | ||
| 
 | ||
|                     if (_ImageUploadList.Any(t => t.StudyInstanceUid == studyInstanceUid))
 | ||
|                     {
 | ||
|                         var find = _ImageUploadList.FirstOrDefault(t => t.StudyInstanceUid.Equals(studyInstanceUid));
 | ||
| 
 | ||
| 
 | ||
|                         find.SuccessImageCount++;
 | ||
| 
 | ||
|                         if (!find.PatientNameList.Any(t => t == patientIdStr) && patientIdStr.IsNotNullOrEmpty())
 | ||
|                         {
 | ||
|                             find.PatientNameList.Add(patientIdStr);
 | ||
|                         }
 | ||
| 
 | ||
|                         //首次 (默认是Guid 空,数据库归档出了Id)
 | ||
|                         if (find.SCPStudyId != scpStudyId)
 | ||
|                         {
 | ||
|                             find.SCPStudyId = scpStudyId;
 | ||
| 
 | ||
|                         }
 | ||
|                     }
 | ||
|                 }
 | ||
|                 catch (Exception ex)
 | ||
|                 {
 | ||
| 
 | ||
|                     Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} 传输处理异常:{ex.ToString()}");
 | ||
| 
 | ||
|                     if (_ImageUploadList.Any(t => t.StudyInstanceUid == studyInstanceUid))
 | ||
|                     {
 | ||
|                         var find = _ImageUploadList.FirstOrDefault(t => t.StudyInstanceUid.Equals(studyInstanceUid));
 | ||
| 
 | ||
|                         find.FailedImageCount++;
 | ||
| 
 | ||
|                     }
 | ||
| 
 | ||
|                 }
 | ||
| 
 | ||
|             }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|             //监控信息设置
 | ||
|             _upload.FileCount++;
 | ||
|             _upload.FileSize = _upload.FileSize + fileSize;
 | ||
|             return new DicomCStoreResponse(request, DicomStatus.Success);
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         public Task OnCStoreRequestExceptionAsync(string tempFileName, Exception e)
 | ||
|         {
 | ||
|             // let library handle logging and error response
 | ||
|             return Task.CompletedTask;
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         public Task<DicomCEchoResponse> OnCEchoRequestAsync(DicomCEchoRequest request)
 | ||
|         {
 | ||
|             return Task.FromResult(new DicomCEchoResponse(request, DicomStatus.Success));
 | ||
|         }
 | ||
| 
 | ||
|     }
 | ||
| }
 |