diff --git a/IRC.Core.SCP/Service/CStoreSCPService.cs b/IRC.Core.SCP/Service/CStoreSCPService.cs index c4b72b89e..11270659d 100644 --- a/IRC.Core.SCP/Service/CStoreSCPService.cs +++ b/IRC.Core.SCP/Service/CStoreSCPService.cs @@ -490,25 +490,9 @@ namespace IRaCIS.Core.SCP.Service uint botOffset = 0; + //需要拆成固定片段的 if (syntax.IsEncapsulated && fragmentCount == pixelData.NumberOfFrames) { - //// ① 先复制 Dataset(非常关键) - //var newDataset = dicomFile.Dataset.Clone(); - - //// ② 从“旧 dataset”读 PixelData - //var srcPd = DicomPixelData.Create(dicomFile.Dataset); - - //// ③ 在“新 dataset”中创建新的 PixelData - //var dstPd = DicomPixelData.Create(newDataset, true); - - //// ④ 重建 PixelData(自动 BOT) - //for (int i = 0; i < srcPd.NumberOfFrames; i++) - //{ - // var frame = srcPd.GetFrame(i); - // dstPd.AddFrame(frame); - //} - - var newFragments = new DicomOtherByteFragment(DicomTag.PixelData); for (int n = 0; n < pixelData.NumberOfFrames; n++) @@ -555,9 +539,57 @@ namespace IRaCIS.Core.SCP.Service ms.SetLength(0); dicomFile.Save(ms); } + //传递过来的就是拆分的,但是是没有偏移表的,我需要自己创建偏移表,不然生成缩略图失败 + else if (syntax.IsEncapsulated && fragmentCount > pixelData.NumberOfFrames && originOffsetTable.Count==0) + { + + uint offset = 0; + + bot.Add(offset); + + var fistSize = frag.Fragments.FirstOrDefault()?.Size??0; + + //和上一个大小不一样 + var isDiffrentBefore = false; + + // 假设你知道每帧对应的 fragment 数量 + foreach (var frameFragments in frag.Fragments) + { + if(frameFragments.Size== fistSize) + { + isDiffrentBefore = false; + // 累加这一帧所有 fragment 的大小 + offset += (uint)frameFragments.Size; + continue; + } + else + { + offset += (uint)frameFragments.Size; + isDiffrentBefore = true; + + } + + if (isDiffrentBefore) + { + bot.Add(offset); + + } + + } + + bot.RemoveAt(bot.Count - 1); + // 设置到新的 PixelData + frag.OffsetTable.AddRange(bot.ToArray()); + + + // 重新保存 DICOM 到流 + ms.SetLength(0); + dicomFile.Save(ms); + + } + - ms.Position = 0; #endregion @@ -573,11 +605,126 @@ namespace IRaCIS.Core.SCP.Service #endregion - + ms.Position = 0; //irc 从路径最后一截取Guid storeRelativePath = await ossService.UploadToOSSAsync(ms, ossFolderPath, instanceId.ToString(), false); fileSize = ms.Length; + + + var @lock = _distributedLockProvider.CreateLock($"{studyInstanceUid}"); + + using (await @lock.AcquireAsync()) + { + try + { + var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(dicomFile, 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(dicomFile.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.BatchUpdateNoTrackingAsync(t => t.Id == seriesId, u => new SCPSeries() { 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; + + #region 给检查打课题组标签 + + //添加课题组标签 + if (CurrentHospitalGroup != null) + { + if (!_studyGroupRepository.Any(t => t.SCPStudyId == scpStudyId && t.HospitalGroupId == CurrentHospitalGroup.Id)) + { + await _studyGroupRepository.AddAsync(new SCPStudyHospitalGroup() { SCPStudyId = scpStudyId, HospitalGroupId = CurrentHospitalGroup.Id }); + } + } + else + { + var findCmoveInfo = _cmoveStudyRepository.Where(t => t.StudyInstanceUIDList.Any(c => c == studyInstanceUid)).OrderByDescending(t => t.CreateTime).FirstOrDefault(); + + if (findCmoveInfo != null) + { + foreach (var item in findCmoveInfo.HopitalGroupIdList) + { + if (!_studyGroupRepository.Any(t => t.SCPStudyId == scpStudyId && t.HospitalGroupId == item)) + { + await _studyGroupRepository.AddAsync(new SCPStudyHospitalGroup() { SCPStudyId = scpStudyId, HospitalGroupId = item }); + + } + } + } + else + { + Log.Logger.Warning($"未找到{studyInstanceUid}的Cmove记录"); + } + } + #endregion + + } + } + } + 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; + } } Log.Logger.Information($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} {request.SOPInstanceUID} 上传完成 "); @@ -588,122 +735,9 @@ namespace IRaCIS.Core.SCP.Service Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE} 上传异常 {ec.Message}"); } + return new DicomCStoreResponse(request, DicomStatus.Success); - var @lock = _distributedLockProvider.CreateLock($"{studyInstanceUid}"); - - using (await @lock.AcquireAsync()) - { - try - { - var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(request.File, 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.BatchUpdateNoTrackingAsync(t => t.Id == seriesId, u => new SCPSeries() { 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; - - #region 给检查打课题组标签 - - //添加课题组标签 - if (CurrentHospitalGroup != null) - { - if (!_studyGroupRepository.Any(t => t.SCPStudyId == scpStudyId && t.HospitalGroupId == CurrentHospitalGroup.Id)) - { - await _studyGroupRepository.AddAsync(new SCPStudyHospitalGroup() { SCPStudyId = scpStudyId, HospitalGroupId = CurrentHospitalGroup.Id }); - } - } - else - { - var findCmoveInfo = _cmoveStudyRepository.Where(t => t.StudyInstanceUIDList.Any(c => c == studyInstanceUid)).OrderByDescending(t => t.CreateTime).FirstOrDefault(); - - if (findCmoveInfo != null) - { - foreach (var item in findCmoveInfo.HopitalGroupIdList) - { - if (!_studyGroupRepository.Any(t => t.SCPStudyId == scpStudyId && t.HospitalGroupId == item)) - { - await _studyGroupRepository.AddAsync(new SCPStudyHospitalGroup() { SCPStudyId = scpStudyId, HospitalGroupId = item }); - - } - } - } - else - { - Log.Logger.Warning($"未找到{studyInstanceUid}的Cmove记录"); - } - } - #endregion - - } - } - } - 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); - } } diff --git a/IRC.Core.SCP/Service/DicomArchiveService.cs b/IRC.Core.SCP/Service/DicomArchiveService.cs index b0460d7d6..c3321a4eb 100644 --- a/IRC.Core.SCP/Service/DicomArchiveService.cs +++ b/IRC.Core.SCP/Service/DicomArchiveService.cs @@ -315,7 +315,7 @@ namespace IRaCIS.Core.SCP.Service SliceLocation = dataset.GetSingleValueOrDefault(DicomTag.SliceLocation, 0), SliceThickness = dataset.GetSingleValueOrDefault(DicomTag.SliceThickness, string.Empty), - NumberOfFrames = dataset.GetSingleValueOrDefault(DicomTag.NumberOfFrames, 0), + NumberOfFrames = dataset.GetSingleValueOrDefault(DicomTag.NumberOfFrames, 1), PixelSpacing = dataset.GetSingleValueOrDefault(DicomTag.PixelSpacing, string.Empty), ImagerPixelSpacing = dataset.GetSingleValueOrDefault(DicomTag.ImagerPixelSpacing, string.Empty), FrameOfReferenceUID = dataset.GetSingleValueOrDefault(DicomTag.FrameOfReferenceUID, string.Empty), diff --git a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs index 77987a8ca..df3fab776 100644 --- a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs +++ b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs @@ -894,10 +894,10 @@ namespace IRaCIS.Core.API.Controllers #endregion - [HttpGet("download/PatientStudyBatchDownload")] + [HttpPost("download/PatientStudyBatchDownload")] public async Task DownloadPatientStudyBatch([FromServices] IPatientService _patientService, [FromServices] IOSSService _oSSService, [FromServices] IHubContext _downLoadHub, - [FromQuery] PatientImageDownloadCommand inCommand) + PatientImageDownloadCommand inCommand) { inCommand.SCPStudyIdList = inCommand.SCPStudyIdList.Where(t => t != Guid.Empty).ToList(); var rusult = await _patientService.GetDownloadPatientStudyInfo(inCommand); @@ -1100,9 +1100,9 @@ namespace IRaCIS.Core.API.Controllers [HttpPost("download/VisitImageDownload")] public async Task VisitImageDownload([FromServices] IPatientService _patientService, [FromServices] IOSSService _oSSService, - [FromServices] IHubContext _downLoadHub, + [FromServices] IHubContext _downLoadHub, [FromServices] IRepository _trialRepository, - VisitImageDownloadCommand inCommand) + VisitImageDownloadCommand inCommand) { var rusult = await _patientService.GetDownloadSubjectVisitStudyInfo(inCommand); diff --git a/IRaCIS.Core.Application/Service/Visit/DTO/PatientViewModel.cs b/IRaCIS.Core.Application/Service/Visit/DTO/PatientViewModel.cs index e9c0eb951..817997967 100644 --- a/IRaCIS.Core.Application/Service/Visit/DTO/PatientViewModel.cs +++ b/IRaCIS.Core.Application/Service/Visit/DTO/PatientViewModel.cs @@ -291,6 +291,8 @@ namespace IRaCIS.Application.Contracts public List ViewPatientHospitalGroupTagList => PatientHospitalGroupTagList.Where(t => CurrentUserHospitalGroupList.Contains(t.HospitalGroupName)).ToList(); + //public long? FileSize { get; set; } + } public class PatientTagView diff --git a/IRaCIS.Core.Application/Service/Visit/PatientService.cs b/IRaCIS.Core.Application/Service/Visit/PatientService.cs index 2313fa8de..3e6d9390a 100644 --- a/IRaCIS.Core.Application/Service/Visit/PatientService.cs +++ b/IRaCIS.Core.Application/Service/Visit/PatientService.cs @@ -55,7 +55,7 @@ namespace IRaCIS.Application.Services public class PatientService(IRepository _studySubjectVisitRepository, IRepository _trialIdentityUserRepository, IRepository _SCPStudyRepository, IOSSService _oSSService, - IRepository _dicomStudyRepository, + IRepository _dicomStudyRepository, IRepository _identityUserRepository, IRepository _subjectPatientRepository, IRepository _SCPStudyHospitalGroupRepository, IRepository _trialRepository, @@ -776,8 +776,9 @@ namespace IRaCIS.Application.Services StudyHospitalGroupList = patient.SCPStudyList.SelectMany(t => t.HospitalGroupList).Select(t => t.HospitalGroup.Name).Distinct().ToList(), PatientHospitalGroupTagList = patient.PatientHospitalGroupTagList - .Select(t => new PatientTagView() { HospitalGroupName = t.HospitalGroupTag.HospitalGroup.Name, HospitalGroupTagName = t.HospitalGroupTag.Name }).ToList() + .Select(t => new PatientTagView() { HospitalGroupName = t.HospitalGroupTag.HospitalGroup.Name, HospitalGroupTagName = t.HospitalGroupTag.Name }).ToList(), + //FileSize = patient.SCPStudyList.Where(t => isAdminOrOA ? true : t.HospitalGroupList.Any(c => currentUserHospitalGroupIdList.Contains(c.HospitalGroupId))).SelectMany(t => t.InstanceList).Sum(t => t.FileSize) }; @@ -3387,8 +3388,8 @@ namespace IRaCIS.Application.Services var query = _patientRepository.Where(t => patientIdList.Contains(t.Id)).Select(t => new DownloadPatientDto() { - PatientName= t.PatientName, - PatientIdStr= t.PatientIdStr, + PatientName = t.PatientName, + PatientIdStr = t.PatientIdStr, StudyList = t.SCPStudyList.Where(t => studyIdList.Count > 0 ? studyIdList.Contains(t.Id) : true) .Where(t => isAdminOrOA ? true : t.HospitalGroupList.Any(c => currentUserHospitalGroupIdList.Contains(c.HospitalGroupId))) @@ -3443,7 +3444,7 @@ namespace IRaCIS.Application.Services Id = NewId.NextSequentialGuid(), IP = _userInfo.IP, DownloadStartTime = DateTime.Now, - StudyCount= patientList.SelectMany(t => t.StudyList).Count(), + StudyCount = patientList.SelectMany(t => t.StudyList).Count(), ImageCount = patientList.SelectMany(t => t.StudyList).Sum(s => s.SeriesList.Sum(s => s.InstanceList.Count())), ImageSize = patientList.SelectMany(t => t.StudyList).Sum(t => t.SeriesList.Sum(s => s.InstanceList.Sum(i => i.FileSize))) ?? 0 }; @@ -3460,7 +3461,7 @@ namespace IRaCIS.Application.Services /// 获取下载的访视检查信息 /// /// - public async Task >> GetDownloadSubjectVisitStudyInfo(VisitImageDownloadCommand inCommand) + public async Task>> GetDownloadSubjectVisitStudyInfo(VisitImageDownloadCommand inCommand) { var dirDic = new Dictionary(); @@ -3468,15 +3469,15 @@ namespace IRaCIS.Application.Services #region DIR处理导出文件名,并将对应关系上传到OSS里面存储 //有传输语法值的导出 才生成DIR - if (_subjectVisitRepository.Where(t => inCommand.SubjectVisitIdList.Contains(t.Id) ).SelectMany(t => t.StudyList.SelectMany(t => t.InstanceList)).All(c => c.TransferSyntaxUID != string.Empty)) + if (_subjectVisitRepository.Where(t => inCommand.SubjectVisitIdList.Contains(t.Id)).SelectMany(t => t.StudyList.SelectMany(t => t.InstanceList)).All(c => c.TransferSyntaxUID != string.Empty)) { var list = _subjectVisitRepository.Where(t => inCommand.SubjectVisitIdList.Contains(t.Id)).SelectMany(t => t.StudyList) .SelectMany(t => t.InstanceList) .Select(t => new StudyDIRInfo() { - SubjectId=t.SubjectId, - TrialId=t.TrialId, - SubjectVisitId=t.SubjectVisitId, + SubjectId = t.SubjectId, + TrialId = t.TrialId, + SubjectVisitId = t.SubjectVisitId, DicomStudyId = t.DicomStudy.Id, PatientId = t.DicomStudy.PatientId, @@ -3511,7 +3512,7 @@ namespace IRaCIS.Application.Services //var pathInfoList = await _subjectVisitRepository.Where(t => inCommand.SubjectVisitIdList.Contains(t.Id)).Select(t => new { t.TrialId, t.SubjectId, VisitId = t.Id }).ToListAsync(); - foreach (var item in list.GroupBy(t => new { t.StudyInstanceUid, t.DicomStudyId,t.SubjectVisitId,t.TrialId,t.SubjectId })) + foreach (var item in list.GroupBy(t => new { t.StudyInstanceUid, t.DicomStudyId, t.SubjectVisitId, t.TrialId, t.SubjectId })) { var ossFolder = $"{item.Key.TrialId}/Image/{item.Key.SubjectId}/{item.Key.SubjectVisitId}/{item.Key.StudyInstanceUid}"; @@ -3569,7 +3570,7 @@ namespace IRaCIS.Application.Services var visitList = await query.ToListAsync(); - foreach (var item in visitList.SelectMany(t=>t.StudyList).SelectMany(t => t.SeriesList).SelectMany(t => t.InstanceList)) + foreach (var item in visitList.SelectMany(t => t.StudyList).SelectMany(t => t.SeriesList).SelectMany(t => t.InstanceList)) { var key = item.InstanceId.ToString(); if (dirDic.ContainsKey(key)) @@ -3609,7 +3610,7 @@ namespace IRaCIS.Application.Services [HttpGet] public async Task DownloadImageSuccess(Guid trialImageDownloadId) { - await _subejctVisitDownloadRepository.UpdatePartialFromQueryAsync( trialImageDownloadId, u => new SubejctVisitDownload() + await _subejctVisitDownloadRepository.UpdatePartialFromQueryAsync(trialImageDownloadId, u => new SubejctVisitDownload() { DownloadEndTime = DateTime.Now, IsSuccess = true }, true); return ResponseOutput.Ok(); }