191 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			191 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C#
		
	
	
| using FellowOakDicom;
 | ||
| using FellowOakDicom.Media;
 | ||
| using System;
 | ||
| using System.Collections.Generic;
 | ||
| using System.Data;
 | ||
| using System.IO;
 | ||
| using System.Linq;
 | ||
| using System.Text;
 | ||
| using System.Threading.Tasks;
 | ||
| 
 | ||
| namespace IRaCIS.Core.Application.Helper
 | ||
| {
 | ||
| 
 | ||
|     public class StudyDIRInfo
 | ||
|     {
 | ||
|         public Guid SubjectVisitId { get; set; }
 | ||
|         // Study
 | ||
|         public Guid DicomStudyId { get; set; }
 | ||
| 
 | ||
|         public string PatientId { get; set; }
 | ||
|         public string PatientName { get; set; }
 | ||
|         public string PatientBirthDate { get; set; }
 | ||
|         public string PatientSex { get; set; }
 | ||
| 
 | ||
|         public string StudyInstanceUid { get; set; }
 | ||
|         public string StudyId { get; set; }
 | ||
|         public string DicomStudyDate { get; set; }
 | ||
|         public string DicomStudyTime { get; set; }
 | ||
|         public string AccessionNumber { get; set; }
 | ||
|         public string StudyDescription { get; set; }
 | ||
| 
 | ||
|         // Series
 | ||
|         public string SeriesInstanceUid { get; set; }
 | ||
|         public string Modality { get; set; }
 | ||
|         public string DicomSeriesDate { get; set; }
 | ||
|         public string DicomSeriesTime { get; set; }
 | ||
|         public int SeriesNumber { get; set; }
 | ||
|         public string SeriesDescription { get; set; }
 | ||
| 
 | ||
|         // Instance
 | ||
|         public Guid InstanceId { get; set; }
 | ||
|         public string SopInstanceUid { get; set; }
 | ||
|         public string SOPClassUID { get; set; }
 | ||
|         public int InstanceNumber { get; set; }
 | ||
|         public string MediaStorageSOPClassUID { get; set; }
 | ||
|         public string MediaStorageSOPInstanceUID { get; set; }
 | ||
|         public string TransferSytaxUID { get; set; }
 | ||
|     }
 | ||
|     public static class DicomDIRHelper
 | ||
|     {
 | ||
| 
 | ||
|         public static async Task GenerateStudyDIRAndUploadAsync(List<StudyDIRInfo> list, Dictionary<string, string> dic, string ossFolder, IOSSService _oSSService)
 | ||
|         {
 | ||
|             var mappings = new List<string>();
 | ||
|             int index = 1;
 | ||
| 
 | ||
| 
 | ||
|             var dicomDir = new DicomDirectory();
 | ||
| 
 | ||
|             foreach (var item in list.OrderBy(t => t.SeriesNumber).ThenBy(t => t.InstanceNumber))
 | ||
|             {
 | ||
|                 var dicomUid = DicomUID.Enumerate().FirstOrDefault(uid => uid.UID == item.TransferSytaxUID);
 | ||
| 
 | ||
|                 if (dicomUid != null)
 | ||
|                 {
 | ||
|                     var ts = DicomTransferSyntax.Query(dicomUid);
 | ||
| 
 | ||
|                     var dataset = new DicomDataset(ts)
 | ||
|                     {
 | ||
|                         { DicomTag.PatientID, item.PatientId ?? string.Empty },
 | ||
|                         { DicomTag.PatientName, item.PatientName ?? string.Empty },
 | ||
|                         { DicomTag.PatientBirthDate, item.PatientBirthDate ?? string.Empty },
 | ||
|                         { DicomTag.PatientSex, item.PatientSex ?? string.Empty },
 | ||
| 
 | ||
|                         { DicomTag.StudyInstanceUID, item.StudyInstanceUid ?? string.Empty },
 | ||
|                         { DicomTag.StudyID, item.StudyId ?? string.Empty },
 | ||
|                         { DicomTag.StudyDate, item.DicomStudyDate ?? string.Empty },
 | ||
|                         { DicomTag.StudyTime, item.DicomStudyTime ?? string.Empty },
 | ||
|                         { DicomTag.AccessionNumber, item.AccessionNumber ?? string.Empty },
 | ||
|                         { DicomTag.StudyDescription, item.StudyDescription ?? string.Empty },
 | ||
| 
 | ||
|                         { DicomTag.SeriesInstanceUID, item.SeriesInstanceUid ?? string.Empty },
 | ||
|                         { DicomTag.Modality, item.Modality ?? string.Empty },
 | ||
|                         { DicomTag.SeriesDate, item.DicomSeriesDate ?? string.Empty },
 | ||
|                         { DicomTag.SeriesTime, item.DicomSeriesTime ?? string.Empty },
 | ||
|                         { DicomTag.SeriesNumber, item.SeriesNumber.ToString() ?? string.Empty },
 | ||
|                         { DicomTag.SeriesDescription, item.SeriesDescription ?? string.Empty },
 | ||
| 
 | ||
|                         { DicomTag.SOPInstanceUID, item.SopInstanceUid ?? string.Empty },
 | ||
|                         { DicomTag.SOPClassUID, item.SOPClassUID ?? string.Empty },
 | ||
|                         { DicomTag.InstanceNumber, item.InstanceNumber.ToString() ?? string.Empty },
 | ||
|                         { DicomTag.MediaStorageSOPClassUID, item.MediaStorageSOPClassUID ?? string.Empty },
 | ||
|                         { DicomTag.MediaStorageSOPInstanceUID, item.MediaStorageSOPInstanceUID ?? string.Empty },
 | ||
|                         { DicomTag.TransferSyntaxUID, item.TransferSytaxUID ?? string.Empty },
 | ||
|                     };
 | ||
| 
 | ||
|                     var dicomFile = new DicomFile(dataset);
 | ||
| 
 | ||
|                     // 文件名递增格式:IM_00001, IM_00002, ...
 | ||
|                     string filename = $@"IMAGE/IM_{index:D5}";  // :D5 表示补足5位
 | ||
| 
 | ||
|                     mappings.Add($"{filename} => {item.InstanceId}");
 | ||
| 
 | ||
|                     dic.Add(item.InstanceId.ToString(), Path.GetFileName(filename));
 | ||
| 
 | ||
|                     dicomDir.AddFile(dicomFile, filename);
 | ||
| 
 | ||
|                     index++;
 | ||
|                 }
 | ||
| 
 | ||
| 
 | ||
|             }
 | ||
| 
 | ||
|             //有实际的文件
 | ||
|             if (mappings.Count > 0)
 | ||
|             {
 | ||
|                 #region 写入临时路径
 | ||
|                 var tempFilePath = Path.GetTempFileName();
 | ||
| 
 | ||
|                 // 保存 DICOMDIR 到临时文件  不能直接写入到流种
 | ||
|                 await dicomDir.SaveAsync(tempFilePath);
 | ||
| 
 | ||
|                 using (var memoryStream = new MemoryStream(File.ReadAllBytes(tempFilePath)))
 | ||
|                 {
 | ||
|                     // 重置流位置
 | ||
|                     memoryStream.Position = 0;
 | ||
| 
 | ||
|                     await _oSSService.UploadToOSSAsync(memoryStream, ossFolder, "DICOMDIR", false);
 | ||
|                 }
 | ||
| 
 | ||
|                 //清理临时文件
 | ||
|                 File.Delete(tempFilePath);
 | ||
| 
 | ||
|                 #endregion
 | ||
| 
 | ||
|                 #region 映射上传
 | ||
| 
 | ||
|                 // 将映射写入内存流
 | ||
|                 var mappingText = string.Join(Environment.NewLine, mappings);
 | ||
|                 await using var mappingStream = new MemoryStream(Encoding.UTF8.GetBytes(mappingText));
 | ||
| 
 | ||
|                 await _oSSService.UploadToOSSAsync(mappingStream, ossFolder, $"Download_{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}", false);
 | ||
| 
 | ||
|                 #endregion
 | ||
|             }
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         public static StudyDIRInfo ReadDicomDIRInfo(DicomFile dicomFile)
 | ||
|         {
 | ||
|             var dataset = dicomFile.Dataset;
 | ||
| 
 | ||
| 
 | ||
|             var info = new StudyDIRInfo
 | ||
|             {
 | ||
|                 PatientId = dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty),
 | ||
|                 PatientName = dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty),
 | ||
|                 PatientBirthDate = dataset.GetSingleValueOrDefault(DicomTag.PatientBirthDate, string.Empty),
 | ||
|                 PatientSex = dataset.GetSingleValueOrDefault(DicomTag.PatientSex, string.Empty),
 | ||
| 
 | ||
|                 StudyInstanceUid = dataset.GetSingleValueOrDefault(DicomTag.StudyInstanceUID, string.Empty),
 | ||
|                 StudyId = dataset.GetSingleValueOrDefault(DicomTag.StudyID, string.Empty),
 | ||
|                 DicomStudyDate = dataset.GetSingleValueOrDefault(DicomTag.StudyDate, string.Empty),
 | ||
|                 DicomStudyTime = dataset.GetSingleValueOrDefault(DicomTag.StudyTime, string.Empty),
 | ||
|                 AccessionNumber = dataset.GetSingleValueOrDefault(DicomTag.AccessionNumber, string.Empty),
 | ||
|                 StudyDescription = dataset.GetSingleValueOrDefault(DicomTag.StudyDescription, string.Empty),
 | ||
| 
 | ||
|                 SeriesInstanceUid = dataset.GetSingleValueOrDefault(DicomTag.SeriesInstanceUID, string.Empty),
 | ||
|                 Modality = dataset.GetSingleValueOrDefault(DicomTag.Modality, string.Empty),
 | ||
|                 DicomSeriesDate = dataset.GetSingleValueOrDefault(DicomTag.SeriesDate, string.Empty),
 | ||
|                 DicomSeriesTime = dataset.GetSingleValueOrDefault(DicomTag.SeriesTime, string.Empty),
 | ||
|                 SeriesNumber = dataset.GetSingleValueOrDefault(DicomTag.SeriesNumber, 1),
 | ||
|                 SeriesDescription = dataset.GetSingleValueOrDefault(DicomTag.SeriesDescription, string.Empty),
 | ||
| 
 | ||
|                 SopInstanceUid = dataset.GetSingleValueOrDefault(DicomTag.SOPInstanceUID, string.Empty),
 | ||
|                 SOPClassUID = dataset.GetSingleValueOrDefault(DicomTag.SOPClassUID, string.Empty),
 | ||
|                 InstanceNumber = dataset.GetSingleValueOrDefault(DicomTag.InstanceNumber, 1),
 | ||
| 
 | ||
|                 MediaStorageSOPClassUID = dicomFile.FileMetaInfo.GetSingleValueOrDefault(DicomTag.MediaStorageSOPClassUID, string.Empty),
 | ||
|                 MediaStorageSOPInstanceUID = dicomFile.FileMetaInfo.GetSingleValueOrDefault(DicomTag.MediaStorageSOPInstanceUID, string.Empty),
 | ||
| 
 | ||
|                 TransferSytaxUID = dicomFile.FileMetaInfo.GetSingleValueOrDefault(DicomTag.TransferSyntaxUID, string.Empty)
 | ||
|             };
 | ||
| 
 | ||
|             return info;
 | ||
|         }
 | ||
|     }
 | ||
| }
 |