12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208 |
- using SkiaSharp;
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Net;
- using System.Net.Http;
- using System.Text;
- using System.Text.Json;
- using System.Threading;
- using System.Xml.Serialization;
- using Vinno.IUS.Common.Log;
- using Vinno.vCloud.Common.FIS.Helper;
- using Vinno.vCloud.Common.FIS.Storages;
- using Vinno.vCloud.Common.Storage.ObjectStorageInfo;
- using Vinno.vCloud.Common.Vid2;
- using Vinno.vCloud.FIS.CrossPlatform.Common.Helper;
- using Vinno.vCloud.FIS.CrossPlatform.Common.SQLite;
- using Vinno.vCloud.Protocol.Infrastructures;
- using WingInterfaceLibrary.DTO.Comment;
- using WingInterfaceLibrary.DTO.Common;
- using WingInterfaceLibrary.DTO.Measure;
- using WingInterfaceLibrary.DTO.Record;
- using WingInterfaceLibrary.DTO.Storage;
- using WingInterfaceLibrary.Enum;
- using WingInterfaceLibrary.Interface;
- using WingInterfaceLibrary.LiveConsultation;
- using WingInterfaceLibrary.Request.Examine;
- using WingInterfaceLibrary.Request.Storage;
- using WingInterfaceLibrary.ResearchEdition;
- using WingInterfaceLibrary.Result.Examine;
- namespace Vinno.vCloud.Common.FIS.Remedicals
- {
- internal class vCloudScanDataV2 : IvCloudScanData, IDisposable
- {
- private UploadStatus _status;
- private readonly IRemedicalService _remedicalService;
- private readonly IStorageService _storageService;
- private readonly IDeviceService _deviceService;
- private readonly string _token;
- private bool _disposed;
- private const string BreastImageLocation = "BreastImageLocation";
- private const string LiverImageLocation = "LiverImageLocation";
- private const string ThyroidImageLocation = "ThyroidImageLocation";
- private Action<ExamRecordCache> _updateExamRecordCache;
- private Action<ExamRecordCacheForResearch> _updateExamRecordCacheForResearch;
- private Func<string, ResearchProjectDTO> _getResearchProjectDTO;
- /// <inheritdoc />
- /// <summary>
- /// Gets the id of this scan data.
- /// </summary>
- public string Id { get; }
- /// <inheritdoc />
- /// <summary>
- /// Gets the examId of this scan data.
- /// </summary>
- public string ExamId { get; }
- /// <inheritdoc />
- /// <summary>
- /// Gets the patientId in Ultrasound Machine
- /// </summary>
- public string PatientId { get; }
- /// <summary>
- /// Get or set the Patient Id In Server
- /// </summary>
- public string PatientIdInServer { get; set; }
- /// <inheritdoc />
- /// <summary>
- /// Gets or sets the ExamRecordId for this scan data.
- /// </summary>
- public string ExamRecordId { get; set; }
- /// <inheritdoc />
- /// <summary>
- /// Gets the workorder Id.
- /// </summary>
- public string WorkOrderId { get; }
- /// <summary>
- /// 项目Id
- /// </summary>
- public string ProjectCode { get; set; }
- /// <summary>
- /// Img List
- /// </summary>
- public List<ImageItem> ImageList { get; set; }
- public Dictionary<string, string> URMParameters { get; set; }
- /// <summary>
- /// Raised when the status changed.
- /// </summary>
- public event EventHandler StatusChanged;
- /// <inheritdoc />
- /// <summary>
- /// Gets the status of this Scan data.
- /// </summary>
- public UploadStatus Status
- {
- get => _status;
- internal set
- {
- if (_status != value)
- {
- var old = _status;
- _status = value;
- if (_status == UploadStatus.Uploaded || _status == UploadStatus.Deleted)
- {
- Delete(old);
- }
- else
- {
- Move(old, _status);
- }
- OnStatusChanged();
- }
- }
- }
- /// <inheritdoc />
- /// <summary>
- /// Gets the vid file path.
- /// </summary>
- public string VidFilePath { get; private set; }
- /// <summary>
- /// Gets the sd file path.
- /// </summary>
- public string ScanDataFilePath { get; private set; }
- /// <inheritdoc />
- /// <summary>
- /// Gets the description of this scan data.
- /// </summary>
- public string Description { get; }
- /// <inheritdoc />
- /// <summary>
- /// Gets the application of this scan data.
- /// </summary>
- public string Application { get; }
- /// <summary>
- /// Gets the Application Category of this scan data
- /// </summary>
- public string ApplicationCategory { get; }
- /// <inheritdoc />
- /// <summary>
- /// Gets the data type of this scan data.
- /// </summary>
- public VidType DataType { get; }
- /// <inheritdoc />
- /// <summary>
- /// Gets the patient info for this scan data.
- /// </summary>
- public PatientScanInfo PatientInfo { get; }
- /// <summary>
- /// Get the Measure Results
- /// </summary>
- public MeasuredResultsDTO MeasuredResults { get; }
- /// <summary>
- /// Get the comment Results
- /// </summary>
- public ScanImageDTO CommentResults { get; }
- /// <summary>
- /// 是否能重新创建检查(只有魔盒的截图版,且非Server指定的检查才可以)
- /// </summary>
- public bool CanRecreateExamRecord { get; }
- /// <summary>
- /// 是否是截图版(只有魔盒有)
- /// </summary>
- public bool IsScreenShotVersion { get; }
- /// <summary>
- /// 是否是会诊图像
- /// </summary>
- public bool IsConsultationData { get; }
- private bool _isUploadFail;
- public vCloudScanDataV2(string patientId, IvCloudExamRecord record, string id, string vidFilePath,
- VidType dataType, string description, PatientScanInfo patientInfo, UploadStatus status, IRemedicalService remedicalService, IStorageService storageService, IDeviceService deviceService, string token, Action<ExamRecordCache> updateExamRecordCache, MeasuredResultsDTO measuredResults, ScanImageDTO commentResults, bool isScreenShotVersion, bool canRecreateExamRecord, bool isConsultationData, string projectCode, List<ImageItem> imageList, Action<ExamRecordCacheForResearch> updateExamRecordCacheForResearch, Dictionary<string, string> urmParameters, Func<string, ResearchProjectDTO> getResearchProjectDTO)
- {
- PatientId = patientId;
- _status = status;
- _token = token;
- _remedicalService = remedicalService;
- _storageService = storageService;
- _deviceService = deviceService;
- ExamRecordId = record.Id;
- ExamId = record.ExamId;
- WorkOrderId = record.WorkOrderId;
- Id = id;
- DataType = dataType;
- Description = description;
- PatientInfo = patientInfo;
- MeasuredResults = measuredResults;
- CommentResults = commentResults;
- IsScreenShotVersion = isScreenShotVersion;
- CanRecreateExamRecord = canRecreateExamRecord;
- IsConsultationData = isConsultationData;
- ProjectCode = projectCode;
- _updateExamRecordCache = updateExamRecordCache;
- _updateExamRecordCacheForResearch = updateExamRecordCacheForResearch;
- _getResearchProjectDTO = getResearchProjectDTO;
- ImageList = imageList;
- URMParameters = urmParameters;
- //Generate files.
- VidFilePath = GetVidFilePath(_status);
- if (string.Compare(VidFilePath, vidFilePath, StringComparison.OrdinalIgnoreCase) != 0)
- {
- File.Move(vidFilePath, VidFilePath);
- }
- if (description == "FromSonopost")
- {
- Application = string.Empty;
- ApplicationCategory = description;
- }
- else
- {
- using (var vinnoImage = new VinnoImageData(VidFilePath, OperationMode.Open))
- {
- ApplicationCategory = vinnoImage.Probe?.Application?.ApplicationCategoryName;
- Application = vinnoImage.Probe?.Application?.ApplicationName;
- }
- }
- //Save self.
- Save();
- }
- ~vCloudScanDataV2()
- {
- DoDispose();
- }
- private void OnStatusChanged()
- {
- StatusChanged?.Invoke(this, EventArgs.Empty);
- }
- /// <summary>
- /// Delete this scanData and its files.
- /// </summary>
- public void Delete()
- {
- Status = UploadStatus.Deleted;
- }
- /// <summary>
- /// Force update the scan data's status.
- /// </summary>
- /// <param name="status">The new status</param>
- public void ForceUpdateStaus(UploadStatus status)
- {
- Status = status;
- }
- /// <summary>
- /// Force update and save the scan data.
- /// </summary>
- public void Update()
- {
- Save();
- }
- /// <summary>
- /// Get saved scan data file path
- /// </summary>
- /// <param name="status"></param>
- /// <returns></returns>
- private string GetScanDataFilePath(UploadStatus status)
- {
- if (status == UploadStatus.Deleted)
- {
- throw new InvalidOperationException("File already deleted.");
- }
- var subFolder = string.Empty;
- if (status == UploadStatus.Idle || status == UploadStatus.Waiting || status == UploadStatus.Uploading)
- {
- subFolder = "Upload";
- }
- if (status == UploadStatus.Fail || status == UploadStatus.FailBecauseExamIsFinished)
- {
- subFolder = "Failed";
- }
- var folder = GetWorkingFolder(subFolder);
- var fileName = $"{Id}.sd";
- return Path.Combine(folder, fileName);
- }
- private string GetWorkingFolder(string subFolder)
- {
- var folder = Path.Combine(vCloudTerminalV2.WorkingFolder, "RemedicalV2", subFolder);
- DirectoryHelper.CreateDirectory(folder);
- return folder;
- }
- /// <summary>
- /// Get the vid file path.
- /// </summary>
- /// <param name="status"></param>
- /// <returns></returns>
- private string GetVidFilePath(UploadStatus status)
- {
- if (status == UploadStatus.Deleted)
- {
- throw new InvalidOperationException("File already deleted.");
- }
- var subFolder = string.Empty;
- if (status == UploadStatus.Idle || status == UploadStatus.Waiting || status == UploadStatus.Uploading)
- {
- subFolder = "Upload";
- }
- if (status == UploadStatus.Fail || status == UploadStatus.FailBecauseExamIsFinished)
- {
- subFolder = "Failed";
- }
- var folder = GetWorkingFolder(subFolder);
- var fileName = $"{Id}.vid";
- return Path.Combine(folder, fileName);
- }
- /// <summary>
- /// Delete the files
- /// </summary>
- /// <param name="status"></param>
- private void Delete(UploadStatus status)
- {
- var scanDataFilePath = GetScanDataFilePath(status);
- var vidFilePath = GetVidFilePath(status);
- FileHelper.DeleteFile(scanDataFilePath);
- FileHelper.DeleteFile(vidFilePath);
- }
- /// <summary>
- /// Save scan data and vid file to the disk by current status.
- /// </summary>
- private void Save()
- {
- ScanDataFilePath = GetScanDataFilePath(Status);
- this.Serialize(ScanDataFilePath);
- }
- /// <summary>
- /// Move scan data from one to another
- /// </summary>
- /// <param name="source"></param>
- /// <param name="dest"></param>
- private void Move(UploadStatus source, UploadStatus dest)
- {
- var sourceScanDataFilePath = GetScanDataFilePath(source);
- var sourceVidFilePath = GetVidFilePath(source);
- var destScanDataFilePath = GetScanDataFilePath(dest);
- var destVidFilePath = GetVidFilePath(dest);
- if (File.Exists(sourceScanDataFilePath) && !File.Exists(destScanDataFilePath))
- {
- File.Move(sourceScanDataFilePath, destScanDataFilePath);
- ScanDataFilePath = destScanDataFilePath;
- }
- if (File.Exists(sourceVidFilePath) && !File.Exists(destVidFilePath))
- {
- File.Move(sourceVidFilePath, destVidFilePath);
- VidFilePath = destVidFilePath;
- }
- }
- /// <summary>
- /// Upload the data to the vCloud server.
- /// </summary>
- public void Upload(CancellationTokenSource cancellationTokenSource)
- {
- string previewFileToken = string.Empty;
- string coverImageToken = string.Empty;
- ImageLocationDTO imageLocationDTO = null;
- VinnoImage vinnoImage = null;
- VinnoImage compressedImage = null;
- var vidFileNameWithoutExtension = Path.GetFileNameWithoutExtension(VidFilePath);
- if (vCloudServerConfig.Instance.IsUploadThumbnail)
- {
- using (var vinnoImageData = new VinnoImageData(VidFilePath, OperationMode.Open))
- {
- if (vinnoImageData.ImageCount <= 0)
- {
- throw new FileNotFoundException("The VinnoImageData Image Count <=0");
- }
- vinnoImage = vinnoImageData.GetImage(0);
- compressedImage = Compress(vinnoImage);
- }
- var firstImageName = "firstImage_" + vidFileNameWithoutExtension + ".jpg";
- var storageUrl = UploadFile(cancellationTokenSource, firstImageName, vinnoImage?.ImageData);
- if (string.IsNullOrWhiteSpace(storageUrl))
- {
- throw new InvalidOperationException($"Get token failed when Uploading first image");
- }
- coverImageToken = storageUrl;
- var previewImageName = "preview_" + vidFileNameWithoutExtension + ".jpg";
- storageUrl = UploadFile(cancellationTokenSource, previewImageName, compressedImage?.ImageData);
- if (string.IsNullOrWhiteSpace(storageUrl))
- {
- throw new InvalidOperationException($"Get token failed when Uploading preview image");
- }
- previewFileToken = storageUrl;
- imageLocationDTO = GetImageLocation(cancellationTokenSource);
- }
- else
- {
- using (var vinnoImageData = new VinnoImageData(VidFilePath, OperationMode.Open))
- {
- if (vinnoImageData.ImageCount <= 0)
- {
- throw new FileNotFoundException("The VinnoImageData Image Count <=0");
- }
- }
- }
- var url = UploadFile(cancellationTokenSource, VidFilePath);
- if (string.IsNullOrWhiteSpace(url))
- {
- throw new InvalidOperationException("Get token failed when Uploading VID file");
- }
- var fileType = RemedicalFileDataTypeEnum.VinnoVidSingle;
- switch (DataType)
- {
- case VidType.VinnoVidMovie:
- fileType = RemedicalFileDataTypeEnum.VinnoVidMovie;
- break;
- case VidType.ThirdVidSingle:
- fileType = RemedicalFileDataTypeEnum.ThirdVidSingle;
- break;
- case VidType.ThirdVidMovie:
- fileType = RemedicalFileDataTypeEnum.ThirdVidMovie;
- break;
- }
- var fileInfo = new FileInfo(VidFilePath);
- var fileSize = fileInfo.Length;
- if (IsConsultationData)
- {
- var uploadConsultationDataRequest = new UploadConsultationDataRequest
- {
- Token = _token,
- ConsultationCode = ExamRecordId,
- FileToken = url,
- FileSize = fileSize,
- Application = Application,
- ApplicationCategory = ApplicationCategory,
- FileDataType = fileType,
- PreviewFileToken = previewFileToken,
- CoverImageToken = coverImageToken,
- MeasuredResult = MeasuredResults,
- CommentResult = CommentResults,
- };
- if (cancellationTokenSource.IsCancellationRequested)
- {
- throw new OperationCanceledException("Cancelled");
- }
- var result = JsonRpcHelper.UploadConsultationData(_deviceService, uploadConsultationDataRequest);
- if (!result)
- {
- throw new InvalidDataException($"JsonRPCHelper UploadExamData Result is false");
- }
- else
- {
- Status = UploadStatus.Uploaded;
- return;
- }
- }
- else
- {
- List<ImgItem> imgList = new List<ImgItem>();
- if (ImageList != null)
- {
- foreach (var image in ImageList)
- {
- var imageInfo = new FileInfo(image.FilePath);
- var imageSize = imageInfo.Length;
- var imageToken = UploadFile(cancellationTokenSource, image.FilePath);
- if (string.IsNullOrWhiteSpace(imageToken))
- {
- throw new InvalidOperationException($"Get token failed when Uploading image file: {image.FilePath}");
- }
- imgList.Add(new ImgItem
- {
- FileToken = imageToken,
- ImgType = image.ImgType,
- FileSize = imageSize,
- });
- }
- }
- var uploadExamDataRequest = new UploadExamDataRequest
- {
- Token = _token,
- ExamCode = ExamRecordId,
- FileToken = url,
- FileSize = fileSize,
- Application = Application,
- ApplicationCategory = ApplicationCategory,
- FileDataType = fileType,
- PreviewFileToken = previewFileToken,
- CoverImageToken = coverImageToken,
- MeasuredResult = MeasuredResults,
- CommentResult = CommentResults,
- ImageLocation = imageLocationDTO,
- ExamTime = PatientInfo.ExamTime,
- ProjectCode = ProjectCode,
- ImgList = imgList,
- UrmParameters = URMParameters,
- };
- if (cancellationTokenSource.IsCancellationRequested)
- {
- throw new OperationCanceledException("Cancelled");
- }
- var result = JsonRpcHelper.UploadExamData(_remedicalService, uploadExamDataRequest);
- if (result == null)
- {
- throw new InvalidDataException($"JsonRPCHelper UploadExamData Result is null");
- }
- else if (result.IsSuccess)
- {
- Status = UploadStatus.Uploaded;
- return;
- }
- else if (!result.IsSuccess)
- {
- if (result.ErrorCode == 4002)//检查已结束扫查,无法继续传图
- {
- if (!CanRecreateExamRecord)
- {
- Status = UploadStatus.FailBecauseExamIsFinished;
- Save();
- return;
- }
- else
- {
- if (CreateExamRecord(string.Empty, out var newExamRecordId))
- {
- ExamRecordId = newExamRecordId;
- uploadExamDataRequest.ExamCode = ExamRecordId;
- if (string.IsNullOrEmpty(ProjectCode))
- {
- var examRecordCache = new ExamRecordCache(ExamId, newExamRecordId, WorkOrderId);
- _updateExamRecordCache(examRecordCache);
- }
- else
- {
- var examRecordCacheForResearch = new ExamRecordCacheForResearch(ExamId, newExamRecordId, WorkOrderId, ProjectCode);
- _updateExamRecordCacheForResearch(examRecordCacheForResearch);
- }
- result = JsonRpcHelper.UploadExamData(_remedicalService, uploadExamDataRequest);
- if (result == null)
- {
- throw new InvalidDataException($"JsonRPCHelper UploadExamData Result is null");
- }
- else if (result.IsSuccess)
- {
- Status = UploadStatus.Uploaded;
- return;
- }
- else
- {
- throw new InvalidDataException($"JsonRPCHelper UploadExamData Fail,Error Code is {result.ErrorCode}");
- }
- }
- else
- {
- throw new InvalidDataException($"JsonRPCHelper UploadExamData Fail:FailBecauseExamIsFinished and ReCreateExamRecord Result is false");
- }
- }
- }
- else if (result.ErrorCode == 4015)//会诊记录不存在
- {
- if (CreateExamRecord(ExamRecordId, out var newExamRecordId))
- {
- if (ExamRecordId == newExamRecordId)
- {
- result = JsonRpcHelper.UploadExamData(_remedicalService, uploadExamDataRequest);
- if (result == null)
- {
- throw new InvalidDataException($"JsonRPCHelper UploadExamData Result is null");
- }
- else if (result.IsSuccess)
- {
- Status = UploadStatus.Uploaded;
- return;
- }
- else
- {
- throw new InvalidDataException($"JsonRPCHelper UploadExamData Fail,Error Code is {result.ErrorCode}");
- }
- }
- else
- {
- if (string.IsNullOrEmpty(ProjectCode))
- {
- throw new InvalidDataException($"JsonRPCHelper UploadExamData Fail:ReCreateExamRecord Result is false,OldExamRecordCode:{ExamRecordId},newExamRecordCode:{newExamRecordId}");
- }
- else
- {
- ExamRecordId = newExamRecordId;
- uploadExamDataRequest.ExamCode = newExamRecordId;
- var examRecordCacheForResearch = new ExamRecordCacheForResearch(ExamId, newExamRecordId, WorkOrderId, ProjectCode);
- _updateExamRecordCacheForResearch(examRecordCacheForResearch);
- result = JsonRpcHelper.UploadExamData(_remedicalService, uploadExamDataRequest);
- if (result == null)
- {
- throw new InvalidDataException($"JsonRPCHelper UploadExamData Result is null");
- }
- else if (result.IsSuccess)
- {
- Status = UploadStatus.Uploaded;
- return;
- }
- else
- {
- throw new InvalidDataException($"JsonRPCHelper UploadExamData Fail,Error Code is {result.ErrorCode}");
- }
- }
- }
- }
- else
- {
- throw new InvalidDataException($"JsonRPCHelper UploadExamData Fail:ReCreateExamRecord Result is false");
- }
- }
- else
- {
- throw new InvalidDataException($"JsonRPCHelper UploadExamData Fail,Error Code is {result.ErrorCode}");
- }
- }
- }
- Status = UploadStatus.Fail;
- }
- private ImageLocationDTO GetImageLocation(CancellationTokenSource cancellationTokenSource)
- {
- if (cancellationTokenSource.IsCancellationRequested)
- {
- throw new OperationCanceledException("Cancelled");
- }
- using (var vinnoImage = new VinnoImageData(VidFilePath, OperationMode.Open))
- {
- var imageLocationExtenedData = VidExtendedData.FromBytes(vinnoImage.ExtendedData);
- if (imageLocationExtenedData != null && imageLocationExtenedData.Data != null)
- {
- var positionTag = imageLocationExtenedData.Data.Keys.FirstOrDefault(t => t.Element == "Position" && t.Group == BreastImageLocation);
- var quadrantTag = imageLocationExtenedData.Data.Keys.FirstOrDefault(t => t.Element == "Quadrant" && t.Group == BreastImageLocation);
- if (positionTag != null && quadrantTag != null)
- {
- if (Enum.TryParse<Position>(imageLocationExtenedData.Data[positionTag].GetValue()?.ToString(), out var positionEnum)
- && Enum.TryParse<QuadrantEnum>(imageLocationExtenedData.Data[quadrantTag].GetValue()?.ToString(), out var quadrantEnum))
- {
- return new ImageLocationDTO
- {
- Position = positionEnum.ToString(),
- Quadrant = quadrantEnum.ToString(),
- Group = positionTag.Group,
- };
- }
- }
- positionTag = imageLocationExtenedData.Data.Keys.FirstOrDefault(t => t.Element == "Position" && t.Group == LiverImageLocation);
- if (positionTag != null)
- {
- if (Enum.TryParse<LiverPosition>(imageLocationExtenedData.Data[positionTag].GetValue()?.ToString(), out var positionEnum))
- {
- return new ImageLocationDTO
- {
- Position = positionEnum.ToString(),
- Group = positionTag.Group,
- };
- }
- }
- positionTag = imageLocationExtenedData.Data.Keys.FirstOrDefault(t => t.Element == FISTissueCategory.Position && !string.IsNullOrWhiteSpace(t.Group));
- var groupName = positionTag?.Group;
- if (positionTag != null && !imageLocationExtenedData.Data.Keys.Any(x => x.Group == groupName && x.Element != FISTissueCategory.Position))
- {
- return new ImageLocationDTO
- {
- Group = groupName,
- Position = imageLocationExtenedData.Data[positionTag].GetValue()?.ToString(),
- };
- }
- }
- }
- return null;
- }
- /// <inheritdoc />
- /// <summary>
- /// Create an exam record from vCloud.
- /// </summary>
- /// <param name="examId">The local excam id.</param>
- /// <param name="workOrderId">The workerId</param>
- /// <param name="patientInfo">The patient basic info for creating the exam record.</param>
- /// <returns><see cref="T:Vinno.vCloud.Terminal.Remedicals.IvCloudExamRecord" /></returns>
- private bool CreateExamRecord(string examRecordId, out string newExamRecordId)
- {
- CreateExaminfoRequest createExaminfoRequest = null;
- var patientType = vCloudServerConfig.Instance.PatientType;
- if (!string.IsNullOrEmpty(ProjectCode))
- {
- var researchProjectDTO = _getResearchProjectDTO.Invoke(ProjectCode);
- if (researchProjectDTO != null)
- {
- patientType = researchProjectDTO.PatientType;
- }
- else
- {
- newExamRecordId = string.Empty;
- Logger.WriteLineError($"GetResearchProjectDTO Fail, result is null, ProjectCode:{ProjectCode} ");
- return false;
- }
- }
- createExaminfoRequest = new CreateExaminfoRequest
- {
- Token = _token,
- PatientType = patientType.ToString(),
- ExamRecordCode = examRecordId,
- PatientInfo = DTOConverter.RenderPatientInfo(PatientInfo, ExamId, patientType),
- PatientScanInfoList = DTOConverter.RenderPatientScanInfo(PatientInfo),
- IsScreenshotVersion = IsScreenShotVersion,
- PatientCode = PatientIdInServer,
- ExamTime = PatientInfo.ExamTime,
- ProjectCode = ProjectCode,
- };
- CreateExaminfoResult result = JsonRpcHelper.CreateExamInfo(_remedicalService, createExaminfoRequest);
- if (result == null || string.IsNullOrEmpty(result.ExamCode))
- {
- newExamRecordId = string.Empty;
- return false;
- }
- else
- {
- newExamRecordId = result.ExamCode;
- return true;
- }
- }
- private string UploadFile(CancellationTokenSource cancellationTokenSource, string filePath)
- {
- FlieSpliceInfo fileSpliceInfo = null;
- var resultDic = new ConcurrentDictionary<int, PartInfo>();
- int divisionSize = 10 * 1024 * 1024;//10MB分一块
- _isUploadFail = false;
- try
- {
- if (cancellationTokenSource.IsCancellationRequested)
- {
- throw new OperationCanceledException("Cancelled");
- }
- var fileName = Path.GetFileName(filePath);
- fileSpliceInfo = UploadFileHelper.ReadFileData(filePath, divisionSize, 0);
- if (fileSpliceInfo == null)
- {
- throw new ArgumentNullException("fileSpliceInfo is null");
- }
- if (fileSpliceInfo.TotalCount == 1)
- {
- return UploadFile(cancellationTokenSource, filePath, fileName);
- }
- else
- {
- var extension = Path.GetExtension(filePath);
- var newFileName = Guid.NewGuid().ToString("N").ToUpper() + extension;
- var fileServiceRequest = new FileServiceRequest
- {
- FileName = newFileName,
- IsRechristen = false,
- Token = _token,
- RequestMethod = "post",
- };
- var authorizationInfo = JsonRpcHelper.GetAuthorization(_storageService, fileServiceRequest);
- if (authorizationInfo == null)
- {
- throw new Exception("GetAuthorization Error,AuthorizationInfo is null ");
- }
- var url = authorizationInfo.StorageUrl + "?uploads";
- InitiateMultipartUploadResult initiateMultipartUploadResult = null;
- using (var request = new HttpRequestMessage(HttpMethod.Post, new Uri(url)))
- {
- request.Headers.TryAddWithoutValidation("Authorization", authorizationInfo.Authorization);
- request.Headers.TryAddWithoutValidation("Content-Type", "application/x-zip-compressed");
- request.Headers.TryAddWithoutValidation("Content-Length", "0");
- using (var httpClient = new HttpClient())
- {
- httpClient.Timeout = TimeSpan.FromMinutes(5);
- var response = httpClient.SendAsync(request, cancellationTokenSource.Token).GetAwaiter().GetResult();
- if (response != null && response.StatusCode == HttpStatusCode.OK)
- {
- if (cancellationTokenSource.IsCancellationRequested)
- {
- throw new OperationCanceledException("Cancelled");
- }
- var result = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
- try
- {
- using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(result.Replace("\\\"", "'").Replace("\\r", "").Replace("\\n", "").Replace("utf-16", "utf-8"))))
- {
- var xml = new XmlSerializer(typeof(InitiateMultipartUploadResult));
- initiateMultipartUploadResult = (InitiateMultipartUploadResult)xml.Deserialize(stream);
- Logger.WriteLineInfo($"InitiateMultipartUpload Success,InitiateMultipartUploadResult:{JsonSerializer.Serialize(initiateMultipartUploadResult)}");
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"InitiateMultipartUpload Error,result:{result?.Trim()},Error:{ex.Message}");
- return UploadFile(cancellationTokenSource, filePath, fileName);
- }
- }
- else
- {
- Logger.WriteLineError($"InitiateMultipartUpload Fail,StatusCode:{response?.StatusCode},Start to normal upload.");
- return UploadFile(cancellationTokenSource, filePath, fileName);
- }
- }
- }
- //分块上传
- fileSpliceInfo.FileSpilceDic.Keys.OrderBy(c => c).AsParallel().WithDegreeOfParallelism(5).ForAll((key) =>
- {
- MultiPartUpload(cancellationTokenSource, key, resultDic, newFileName, initiateMultipartUploadResult?.UploadId, fileSpliceInfo.FileSpilceDic[key]);
- });
- bool isReadAllBytes = fileSpliceInfo.IsReadAllBytes;
- int fileCount = 0;
- while (!isReadAllBytes)
- {
- if (resultDic.Count - fileCount != fileSpliceInfo.FileSpilceDic.Count)
- {
- Logger.WriteLineInfo($"MultipartUpload Fail:FileSpilceDic Count:{fileSpliceInfo.TotalCount},resultDic Count:{resultDic.Count}");
- return string.Empty;
- }
- fileCount = resultDic.Count;
- fileSpliceInfo = UploadFileHelper.ReadFileData(filePath, divisionSize, fileCount);
- if (fileSpliceInfo == null)
- {
- throw new ArgumentNullException("fileSpliceInfo is null");
- }
- fileSpliceInfo.FileSpilceDic.Keys.OrderBy(c => c).AsParallel().WithDegreeOfParallelism(5).ForAll((key) =>
- {
- MultiPartUpload(cancellationTokenSource, key, resultDic, newFileName, initiateMultipartUploadResult?.UploadId, fileSpliceInfo.FileSpilceDic[key]);
- });
- isReadAllBytes = fileSpliceInfo.IsReadAllBytes;
- }
- if (resultDic.Count == fileSpliceInfo.TotalCount)
- {
- return CompleteMultipartUpload(cancellationTokenSource, resultDic, newFileName, authorizationInfo, initiateMultipartUploadResult);
- }
- else
- {
- Logger.WriteLineInfo($"MultipartUpload Fail:total Count:{fileSpliceInfo.TotalCount},resultDic Count:{resultDic.Count}");
- return string.Empty;
- }
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"Upload File :{filePath} Error:{ex}");
- return string.Empty;
- }
- }
- private void MultiPartUpload(CancellationTokenSource cancellationTokenSource, int key, ConcurrentDictionary<int, PartInfo> resultDic, string fileName, string uploadId, byte[] bytes)
- {
- var index = key + 1;
- try
- {
- if (cancellationTokenSource.IsCancellationRequested || _isUploadFail)
- {
- Logger.WriteLineError($"MultiPartUpload PartNumber:{index} Cancelled");
- return;
- }
- var requestParams = new List<DataItemDTO>()
- {
- new DataItemDTO
- {
- Key = "partNumber",
- Value = index.ToString()
- },
- new DataItemDTO
- {
- Key = "uploadId",
- Value =uploadId
- }
- };
- var multipartUploadFileServiceRequest = new FileServiceRequest
- {
- FileName = fileName,
- IsRechristen = false,
- Token = _token,
- UrlParams = requestParams,
- };
- var multipartUploadAuthorizationInfo = JsonRpcHelper.GetAuthorization(_storageService, multipartUploadFileServiceRequest, false);
- if (multipartUploadAuthorizationInfo == null)
- {
- throw new Exception("GetAuthorization Error,MultipartUploadAuthorizationInfo is null ");
- }
- if (cancellationTokenSource.IsCancellationRequested)
- {
- Logger.WriteLineError($"MultiPartUpload PartNumber:{index} Cancelled");
- return;
- }
- var multipartUploadUrl = $"{multipartUploadAuthorizationInfo.StorageUrl}?partNumber={index}&uploadId={uploadId}";
- Tuple<bool, string> uploadResult;
- try
- {
- uploadResult = UploadFileHelper.UploadFile(multipartUploadUrl, bytes, multipartUploadAuthorizationInfo.ContentType, multipartUploadAuthorizationInfo.Authorization, null, cancellationTokenSource);
- if (uploadResult == null || !uploadResult.Item1)
- {
- throw new Exception($"Upload file failed! uploadResult Result:{uploadResult?.Item1},ETag:{uploadResult?.Item2}");
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"MultiPartUpload PartNumber:{index}, Error:{ex.Message} once, try again");
- try
- {
- if (cancellationTokenSource.IsCancellationRequested)
- {
- Logger.WriteLineError($"MultiPartUpload PartNumber:{index} Cancelled");
- return;
- }
- uploadResult = UploadFileHelper.UploadFile(multipartUploadUrl, bytes, multipartUploadAuthorizationInfo.ContentType, multipartUploadAuthorizationInfo.Authorization, null, cancellationTokenSource);
- if (uploadResult == null || !uploadResult.Item1)
- {
- throw new Exception($"Upload file failed! uploadResult Result:{uploadResult?.Item1},ETag:{uploadResult?.Item2}");
- }
- }
- catch (Exception e)
- {
- Logger.WriteLineError($"MultiPartUpload PartNumber:{index}, Error:{e.Message} again");
- _isUploadFail = true;
- return;
- }
- }
- if (cancellationTokenSource.IsCancellationRequested)
- {
- Logger.WriteLineError($"MultiPartUpload PartNumber:{index} Cancelled");
- return;
- }
- var tempEntity = new PartInfo()
- {
- PartNumber = index,
- ETag = uploadResult.Item2
- };
- Logger.WriteLineInfo($"MultipartUploadPart PartNumber:{index},ETag:{uploadResult.Item2} success!");
- resultDic.TryAdd(index, tempEntity);
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"MultiPartUpload PartNumber:{index}, Error:{ex.Message}");
- _isUploadFail = true;
- }
- }
- private string CompleteMultipartUpload(CancellationTokenSource cancellationTokenSource, ConcurrentDictionary<int, PartInfo> resultDic, string fileName, StorageServiceSettingDTO authorizationInfo, InitiateMultipartUploadResult initiateMultipartUploadResult)
- {
- var completeEntity = new CompleteMultipartUpload();
- foreach (var key in resultDic.Keys.OrderBy(x => x).ToList())
- {
- completeEntity.Part.Add(resultDic[key]);
- }
- var requestParams = new List<DataItemDTO>()
- {
- new DataItemDTO
- {
- Key = "uploadId",
- Value = initiateMultipartUploadResult.UploadId
- }
- };
- var completeMultipartUploadFileServiceRequest = new FileServiceRequest
- {
- FileName = fileName,
- IsRechristen = false,
- Token = _token,
- UrlParams = requestParams,
- RequestMethod = "post",
- IsCompleted = true,
- };
- var completeMultipartUploadAuthorizationInfo = JsonRpcHelper.GetAuthorization(_storageService, completeMultipartUploadFileServiceRequest);
- if (completeMultipartUploadAuthorizationInfo == null)
- {
- throw new Exception("GetAuthorization Error,CompleteMultipartUploadAuthorizationInfo is null ");
- }
- var completeMultipartUploadUrl = $"{completeMultipartUploadAuthorizationInfo.StorageUrl}?uploadId={initiateMultipartUploadResult.UploadId}";
- var xml = "";
- if (completeEntity.Part?.Count > 0)
- {
- xml = "<CompleteMultipartUpload>";
- foreach (var partInfo in completeEntity.Part)
- {
- xml += "<Part>";
- xml += "<PartNumber>" + partInfo.PartNumber + "</PartNumber>";
- xml += "<ETag>" + partInfo.ETag + "</ETag>";
- xml += "</Part>";
- }
- xml += "</CompleteMultipartUpload>";
- }
- byte[] bytesR = Encoding.UTF8.GetBytes(xml);
- var byteContent = new ByteArrayContent(bytesR);
- var mimeType = HttpClientHelper.GetMimeType(".config");
- using (var request = new HttpRequestMessage(HttpMethod.Post, new Uri(completeMultipartUploadUrl)))
- {
- request.Headers.TryAddWithoutValidation("Authorization", completeMultipartUploadAuthorizationInfo.Authorization);
- request.Headers.TryAddWithoutValidation("Content-Type", mimeType);
- request.Content = byteContent;
- using (var httpClient = new HttpClient())
- {
- var response = httpClient.SendAsync(request, cancellationTokenSource.Token).GetAwaiter().GetResult();
- if (response != null && response.StatusCode == HttpStatusCode.OK)
- {
- if (cancellationTokenSource.IsCancellationRequested)
- {
- throw new OperationCanceledException("Cancelled");
- }
- var result = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
- try
- {
- if (result.Contains(nameof(CompleteMultipartUploadResult)))
- {
- Logger.WriteLineInfo($"CompleteMultipartUpload Success,{result}");
- return authorizationInfo.StorageUrl;
- }
- else
- {
- Logger.WriteLineInfo($"CompleteMultipartUpload Error,{result}");
- return string.Empty;
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineInfo($"CompleteMultipartUpload Fail, result:{result?.Trim()},Error:{ex.Message}");
- return string.Empty;
- }
- }
- else
- {
- Logger.WriteLineError($"CompleteMultipartUpload Fail,StatusCode:{response?.StatusCode}.");
- return string.Empty;
- }
- }
- }
- }
- private string UploadFile(CancellationTokenSource cancellationTokenSource, string filePath, string fileName)
- {
- var fileServiceRequest = new FileServiceRequest
- {
- FileName = fileName,
- IsRechristen = true,
- Token = _token,
- };
- var authorizationInfo = JsonRpcHelper.GetAuthorization(_storageService, fileServiceRequest);
- if (authorizationInfo == null)
- {
- throw new Exception("GetAuthorization Error,AuthorizationInfo is null ");
- }
- if (cancellationTokenSource.IsCancellationRequested)
- {
- throw new OperationCanceledException("Cancelled");
- }
- var uploadResult = UploadFileHelper.UploadFile(authorizationInfo.StorageUrl, filePath, authorizationInfo.ContentType, authorizationInfo.Authorization, null, cancellationTokenSource);
- if (cancellationTokenSource.IsCancellationRequested)
- {
- throw new OperationCanceledException("Cancelled");
- }
- if (uploadResult?.Item1 == true)
- {
- return authorizationInfo.StorageUrl;
- }
- else
- {
- return string.Empty;
- }
- }
- private string UploadFile(CancellationTokenSource cancellationTokenSource, string fileName, byte[] fileData)
- {
- var fileServiceRequest = new FileServiceRequest
- {
- FileName = fileName,
- IsRechristen = true,
- Token = _token,
- };
- var authorizationInfo = JsonRpcHelper.GetAuthorization(_storageService, fileServiceRequest);
- if (authorizationInfo == null)
- {
- throw new Exception("GetAuthorization Error,AuthorizationInfo is null ");
- }
- if (cancellationTokenSource.IsCancellationRequested)
- {
- throw new OperationCanceledException("Cancelled");
- }
- var uploadResult = UploadFileHelper.UploadFile(authorizationInfo.StorageUrl, fileData, authorizationInfo.ContentType, authorizationInfo.Authorization, null, cancellationTokenSource);
- if (cancellationTokenSource.IsCancellationRequested)
- {
- throw new OperationCanceledException("Cancelled");
- }
- if (uploadResult?.Item1 == true)
- {
- return authorizationInfo.StorageUrl;
- }
- else
- {
- return string.Empty;
- }
- }
- private void DoDispose()
- {
- try
- {
- if (!_disposed)
- {
- //if not uploaded just save it to disk.
- if (Status != UploadStatus.Uploaded && Status != UploadStatus.Deleted)
- {
- Save();
- }
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"vCloudScanData: dispose upload data error:{ex}");
- }
- finally
- {
- _disposed = true;
- }
- }
- /// <summary>
- /// Compress a VinnoImage to a 100p image with {compressLevel} quality
- /// </summary>
- /// <param name="vinnoImage"></param>
- /// <param name="compressLevel"></param>
- /// <returns></returns>
- /// <exception cref="Exception"></exception>
- private VinnoImage Compress(VinnoImage vinnoImage, long compressLevel = 80)
- {
- byte[] compressedData = vinnoImage.ImageData;
- using (var ms = new MemoryStream(compressedData))
- {
- using (var image = SKBitmap.Decode(ms))
- {
- var ratio = (double)100 / image.Height;
- if (ratio < 1)
- {
- var width = (int)(image.Width * ratio);
- var height = 100;
- SKBitmap tempImage = image;
- if (image.Width != width || image.Height != height)
- {
- tempImage = image.Resize(new SKImageInfo(width, height), SKFilterQuality.High);
- }
- try
- {
- using (var map = new SKPixmap(new SKImageInfo(tempImage.Width, tempImage.Height, tempImage.ColorType), tempImage.GetPixels()))
- {
- using (var stream = new SKDynamicMemoryWStream())
- {
- SKPixmap.Encode(stream, map, SKEncodedImageFormat.Jpeg, (int)compressLevel);
- compressedData = stream.CopyToData().ToArray();
- }
- }
- }
- catch (Exception exception)
- {
- throw new Exception($"Compress error:{exception}");
- }
- finally
- {
- tempImage.Dispose();
- }
- var compressImage = new VinnoImage(vinnoImage.Index, width, height, compressedData);
- return compressImage;
- }
- }
- }
- return vinnoImage;
- }
- public void Dispose()
- {
- DoDispose();
- GC.SuppressFinalize(this);
- }
- }
- }
|