//-------------------------------------------------------------------- // 此代码由T4模板自动生成 byzhouhang 20210918 // 生成时间 2021-12-06 10:54:55 // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 //-------------------------------------------------------------------- using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using IRaCIS.Core.Domain.Share; using SharpCompress.Archives; using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Infra.EFCore; using Newtonsoft.Json; using IRaCIS.Core.Application.Service.Inspection.Interface; using IRaCIS.Core.Application.Service.Inspection.DTO; namespace IRaCIS.Core.Application.Contracts { /// /// NoneDicomStudyService /// [ApiExplorerSettings(GroupName = "Image")] public class NoneDicomStudyService : BaseService, INoneDicomStudyService { private readonly IRepository _noneDicomStudyRepository; private readonly IHttpContextAccessor _httpContext; private readonly IWebHostEnvironment _hostEnvironment; private readonly IInspectionService _inspectionService; private readonly IRepository _noneDicomStudyFileRepository; public NoneDicomStudyService(IRepository noneDicomStudyRepository, IHttpContextAccessor httpContext, IWebHostEnvironment hostEnvironment, IInspectionService inspectionService, IRepository noneDicomStudyFileRepository) { _noneDicomStudyRepository = noneDicomStudyRepository; this._httpContext = httpContext; this._hostEnvironment = hostEnvironment; this._inspectionService = inspectionService; _noneDicomStudyFileRepository = noneDicomStudyFileRepository; } [HttpGet("{subjectVisitId:guid}")] public async Task> GetNoneDicomStudyList(Guid subjectVisitId) { var noneDicomStudyQueryable = _noneDicomStudyRepository.Where(t => t.SubjectVisitId == subjectVisitId) .ProjectTo(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken }); return await noneDicomStudyQueryable.ToListAsync(); } [UnitOfWork] [TypeFilter(typeof(TrialResourceFilter))] public async Task> AddOrUpdateNoneDicomStudy(NoneDicomStudyAddOrEdit addOrEditNoneDicomStudy) { var entity = await _noneDicomStudyRepository.InsertOrUpdateAsync(addOrEditNoneDicomStudy, false); if (_repository.Entry(entity).State == Microsoft.EntityFrameworkCore.EntityState.Added) { entity.Code = _noneDicomStudyRepository.Where(t => t.TrialId == addOrEditNoneDicomStudy.TrialId).Select(t => t.Code).DefaultIfEmpty().Max() + 1; } entity.StudyCode = "NST" + entity.Code.ToString("D5"); await _repository.SaveChangesAsync(); var svTime = _repository.Where(t => t.Id == addOrEditNoneDicomStudy.SubjectVisitId).Select(t => new { DicomStudyMinStudyTime = t.StudyList.Min(t => (DateTime?)t.StudyTime), DicomStudyMaxStudyTime = t.StudyList.Max(t => (DateTime?)t.StudyTime), NoneDicomStudyMinStudyTime = t.NoneDicomStudyList.Min(t => (DateTime?)t.ImageDate), NoneDicomStudyMaxStudyTime = t.NoneDicomStudyList.Max(t => (DateTime?)t.ImageDate) }).FirstOrDefault().IfNullThrowException(); var minArray = new DateTime?[] { svTime.DicomStudyMinStudyTime, svTime.NoneDicomStudyMinStudyTime, addOrEditNoneDicomStudy.ImageDate }; var maxArray = new DateTime?[] { svTime.DicomStudyMaxStudyTime, svTime.NoneDicomStudyMaxStudyTime, addOrEditNoneDicomStudy.ImageDate }; await _repository.BatchUpdateAsync(t => t.Id == addOrEditNoneDicomStudy.SubjectVisitId, u => new SubjectVisit() { VisitExecuted = VisitExecutedEnum.Executed, EarliestScanDate = minArray.Min(), LatestScanDate = maxArray.Max() }); await _repository.SaveChangesAsync(); NoneDicomStudyAddReturnDto noneDicom = new NoneDicomStudyAddReturnDto() { StudyCode= entity.StudyCode, Id= entity.Id }; return ResponseOutput.Ok(noneDicom); } [TypeFilter(typeof(TrialResourceFilter))] [HttpDelete("{noneDicomStudyId:guid}/{trialId:guid}")] public async Task DeleteNoneDicomStudy(Guid noneDicomStudyId) { if (_noneDicomStudyRepository.Where(t => t.Id == noneDicomStudyId) .Any(t => t.NoneDicomFileList.Count() > 0)) { return ResponseOutput.NotOk("先移除文件,才允许删除非Dicom"); } var noneDicomStudy = await _noneDicomStudyRepository.FirstOrDefaultAsync(t => t.Id == noneDicomStudyId); if (noneDicomStudy == null) return Null404NotFound(noneDicomStudy); await _noneDicomStudyRepository.BatchDeleteAsync(t => t.Id == noneDicomStudyId); await _noneDicomStudyFileRepository.BatchDeleteAsync(t => t.NoneDicomStudyId == noneDicomStudyId); var svTime = await _repository.Where(t => t.Id == noneDicomStudy.SubjectVisitId).Select(t => new { DicomStudyMinStudyTime = t.StudyList.Min(t => (DateTime?)t.StudyTime), DicomStudyMaxStudyTime = t.StudyList.Max(t => (DateTime?)t.StudyTime), NoneDicomStudyMinStudyTime = t.NoneDicomStudyList.Min(t => (DateTime?)t.ImageDate), NoneDicomStudyMaxStudyTime = t.NoneDicomStudyList.Max(t => (DateTime?)t.ImageDate) }).FirstOrDefaultAsync().IfNullThrowException(); var minArray = new DateTime?[] { svTime.DicomStudyMinStudyTime, svTime.NoneDicomStudyMinStudyTime }; var maxArray = new DateTime?[] { svTime.DicomStudyMaxStudyTime, svTime.NoneDicomStudyMaxStudyTime }; await _repository.BatchUpdateAsync(t => t.Id == noneDicomStudy.SubjectVisitId, u => new SubjectVisit() { EarliestScanDate = minArray.Min(), LatestScanDate = maxArray.Max() }); //如果既没有 dicom数据 也没有非dicom 文件 那么提交状态变更回去 if (await _repository.CountAsync(t => t.SubjectVisitId == noneDicomStudy.SubjectVisitId) == 0 && await _repository.CountAsync(t => t.NoneDicomStudy.SubjectVisitId == noneDicomStudy.SubjectVisitId) == 0) { await _repository.BatchUpdateAsync(t => t.Id == noneDicomStudy.SubjectVisitId && t.SubmitState == SubmitStateEnum.ToSubmit, u => new SubjectVisit() { VisitExecuted = 0, SubmitState = SubmitStateEnum.None }); } return ResponseOutput.Ok(); } [HttpDelete("{noneDicomStudyFileId:guid}")] public async Task DeleteNoneDicomStudyFile(Guid noneDicomStudyFileId) { var subjectVisitId = await _noneDicomStudyFileRepository.Where(t=>t.Id== noneDicomStudyFileId).Select(t => t.NoneDicomStudy.SubjectVisitId).FirstOrDefaultAsync(); var success = await _noneDicomStudyFileRepository.BatchDeleteAsync(t => t.Id == noneDicomStudyFileId); //如果既没有 dicom数据 也没有非dicom 文件 那么提交状态变更回去 if (await _repository.CountAsync(t => t.SubjectVisitId == subjectVisitId) == 0 && await _repository.CountAsync(t => t.NoneDicomStudy.SubjectVisitId == subjectVisitId) == 0) { await _repository.BatchUpdateAsync(t => t.Id == subjectVisitId && t.SubmitState == SubmitStateEnum.ToSubmit, u => new SubjectVisit() { VisitExecuted = 0, SubmitState = SubmitStateEnum.None }); } var subvisit = await _repository.GetQueryable().FirstOrDefaultAsync(x => x.Id == subjectVisitId); List datas = new List(); datas.Add(new DataInspection() { SiteId = subvisit.SiteId, SubjectId = subvisit.SubjectId, TrialId = subvisit.TrialId, SubjectVisitId = subvisit.Id, Identification = "Edit|Visit|Status|Visit-Image Upload|Add Image", JsonDetail = JsonConvert.SerializeObject(new { SubmitState = "待提交", }) }); await _inspectionService.AddListInspectionRecordAsync(datas); return ResponseOutput.Ok(); } /// /// 非Dicom检查 文件列表 /// /// /// [HttpGet("{noneDicomStudyId:guid}")] public async Task> GetNoneDicomStudyFileList(Guid noneDicomStudyId) { return await _noneDicomStudyFileRepository.Where(t => t.NoneDicomStudyId == noneDicomStudyId) .ProjectTo(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken }).ToListAsync(); } [HttpGet("{subjectVisitId:guid}")] public async Task> GetVisitNoneDicomStudyFileList(Guid subjectVisitId) { return await _repository.Where(t => t.NoneDicomStudy.SubjectVisitId == subjectVisitId).ProjectTo(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken }).ToListAsync(); } /// /// 上传非Dicom 文件 支持压缩包 /// [HttpPost] public async Task NewUploadNoneDicomFile([FromForm]UploadNoneDicomFileDto fileDto) { var file = this._httpContext.HttpContext?.Request.Form; var result= await UploadNoneDicomFile(file, fileDto.subjectVisitId, fileDto.noneDicomStudyId); if (result.IsSuccess) { var data = JsonConvert.DeserializeObject(fileDto.AuditInfo); data.GeneralId = fileDto.noneDicomStudyId; await _inspectionService.AddInspectionRecordAsync(data); var subvisit =await _repository.GetQueryable().FirstOrDefaultAsync(x => x.Id == fileDto.subjectVisitId); List datas = new List(); datas.Add(new DataInspection() { SiteId = subvisit.SiteId, SubjectId = subvisit.SubjectId, TrialId = subvisit.TrialId, SubjectVisitId = subvisit.Id, Identification = "Edit|Visit|Status|Visit-Image Upload|Add Image", JsonDetail = JsonConvert.SerializeObject(new { SubmitState = "待提交", }) }); await _inspectionService.AddListInspectionRecordAsync(datas); } return result; } /// /// 上传非Dicom 文件 支持压缩包 /// /// /// /// /// /// //[DisableRequestSizeLimit] [RequestSizeLimit(1_073_741_824)] [HttpPost("{noneDicomStudyId:guid}/{subjectVisitId:guid}")] public async Task UploadNoneDicomFile(IFormCollection formCollection, Guid subjectVisitId, Guid noneDicomStudyId) { var rootPath = Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\')).IfNullThrowException().FullName; //上传根路径 var _fileStorePath = Path.Combine(rootPath, StaticData.TrialDataFolder); var sv = await _repository.Where(t => t.Id == subjectVisitId).Select(t => new { t.TrialId, t.SiteId, t.SubjectId }).FirstOrDefaultAsync().IfNullThrowConvertException(); string uploadFolderPath = Path.Combine(_fileStorePath, sv.TrialId.ToString(), sv.SiteId.ToString(), sv.SubjectId.ToString(), subjectVisitId.ToString(), StaticData.NoneDicomFolder); if (!Directory.Exists(uploadFolderPath)) { Directory.CreateDirectory(uploadFolderPath); } var startTime = DateTime.Now; foreach (IFormFile file in formCollection.Files) { if (file.FileName.Contains(".Zip", StringComparison.OrdinalIgnoreCase) || file.FileName.Contains(".rar", StringComparison.OrdinalIgnoreCase)) { var archive = ArchiveFactory.Open(file.OpenReadStream()); foreach (var entry in archive.Entries) { if (!entry.IsDirectory) { DealCompressFile(entry, sv, subjectVisitId, noneDicomStudyId, uploadFolderPath); } } } else { var trustedFileNameForFileStorage = GetStoreFileName(file.FileName); var relativePath = $"/{StaticData.TrialDataFolder}/{sv.TrialId}/{sv.SiteId}/{sv.SubjectId}/{subjectVisitId}/{StaticData.NoneDicomFolder}/{trustedFileNameForFileStorage}"; var filePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); using (FileStream fs = System.IO.File.Create(filePath)) { await file.CopyToAsync(fs); await fs.FlushAsync(); } await _noneDicomStudyFileRepository.AddAsync(new NoneDicomStudyFile() { FileName = file.FileName, Path = relativePath, NoneDicomStudyId = noneDicomStudyId }); } } // 上传非Dicom 后 将状态改为待提交 分为普通上传 和QC后重传 普通上传时才改为待提交 await _repository.BatchUpdateAsync(t => t.Id == subjectVisitId && t.SubmitState == SubmitStateEnum.None, u => new SubjectVisit() { SubmitState = SubmitStateEnum.ToSubmit }); await _repository.AddAsync(new StudyMonitor() { FileCount = formCollection.Files.Count, FileSize = formCollection.Files.Sum(t => t.Length), IsDicom = false, IsDicomReUpload = false, StudyId = noneDicomStudyId, UploadStartTime = startTime, UploadFinishedTime = DateTime.Now, IP = _userInfo.IP, TrialId = sv.TrialId, SiteId = sv.SiteId, SubjectId = sv.SubjectId, SubjectVisitId = subjectVisitId, }); await _repository.SaveChangesAsync(); return ResponseOutput.Ok(/*list*/); } private string GetStoreFileName(string fileName) { var realName = fileName; var fileNameEX = Path.GetExtension(realName); var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileNameEX; return trustedFileNameForFileStorage; } private async void DealCompressFile(IArchiveEntry entry, dynamic sv, Guid subjectVisitId, Guid noneDicomStudyId, string uploadFolderPath) { var trustedFileNameForFileStorage = GetStoreFileName(entry.Key); var relativePath = $"/{StaticData.TrialDataFolder}/{sv.TrialId}/{sv.SiteId}/{sv.SubjectId}/{subjectVisitId}/{StaticData.NoneDicomFolder}/{trustedFileNameForFileStorage}"; var filePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); entry.WriteToFile(filePath); var fileName = string.Empty; if (entry.Key.Contains("\\")) { fileName = entry.Key.Split("\\").Last(); } await _repository.AddAsync(new NoneDicomStudyFile() { FileName = fileName, Path = relativePath, NoneDicomStudyId = noneDicomStudyId }); } } }