1151 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			1151 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C#
		
	
	
| using AutoMapper;
 | ||
| using EasyCaching.Core;
 | ||
| using ExcelDataReader;
 | ||
| using IRaCIS.Application.Contracts;
 | ||
| using IRaCIS.Application.Interfaces;
 | ||
| using IRaCIS.Core.Application.Auth;
 | ||
| using IRaCIS.Core.Application.Contracts;
 | ||
| using IRaCIS.Core.Application.Contracts.Dicom;
 | ||
| using IRaCIS.Core.Application.Contracts.Dicom.DTO;
 | ||
| using IRaCIS.Core.Application.Filter;
 | ||
| using IRaCIS.Core.Application.Helper;
 | ||
| using IRaCIS.Core.Application.MediatR.CommandAndQueries;
 | ||
| using IRaCIS.Core.Application.MediatR.Handlers;
 | ||
| using IRaCIS.Core.Application.Service;
 | ||
| using IRaCIS.Core.Application.Service.Reading.Dto;
 | ||
| using IRaCIS.Core.Domain.Models;
 | ||
| using IRaCIS.Core.Domain.Share;
 | ||
| using IRaCIS.Core.Infra.EFCore;
 | ||
| using IRaCIS.Core.Infrastructure;
 | ||
| using IRaCIS.Core.Infrastructure.Extention;
 | ||
| using Magicodes.ExporterAndImporter.Excel;
 | ||
| using MassTransit;
 | ||
| using MediatR;
 | ||
| using Microsoft.AspNetCore.Authorization;
 | ||
| using Microsoft.AspNetCore.Hosting;
 | ||
| using Microsoft.AspNetCore.Http;
 | ||
| using Microsoft.AspNetCore.Mvc;
 | ||
| using Microsoft.AspNetCore.Mvc.ModelBinding;
 | ||
| using Microsoft.AspNetCore.SignalR;
 | ||
| using Microsoft.AspNetCore.StaticFiles;
 | ||
| using Microsoft.AspNetCore.WebUtilities;
 | ||
| using Microsoft.EntityFrameworkCore;
 | ||
| using Microsoft.Extensions.Logging;
 | ||
| using Microsoft.Net.Http.Headers;
 | ||
| using MiniExcelLibs;
 | ||
| using Newtonsoft.Json;
 | ||
| using SharpCompress.Archives;
 | ||
| using System;
 | ||
| using System.Collections.Generic;
 | ||
| using System.Data;
 | ||
| using System.Globalization;
 | ||
| using System.IO;
 | ||
| using System.Linq;
 | ||
| using System.Text;
 | ||
| using System.Threading.Tasks;
 | ||
| 
 | ||
| namespace IRaCIS.Core.API.Controllers
 | ||
| {
 | ||
| 
 | ||
|     #region 上传基类封装
 | ||
|     [DisableFormValueModelBinding]
 | ||
|     public abstract class UploadBaseController : ControllerBase
 | ||
|     {
 | ||
|         /// <summary>  流式上传  直接返回</summary>
 | ||
|         [Route("base")]
 | ||
|         public virtual async Task<IResponseOutput> SingleFileUploadAsync(Func<string, (string, string)> filePathFunc)
 | ||
|         {
 | ||
|             var boundary = HeaderUtilities.RemoveQuotes(MediaTypeHeaderValue.Parse(Request.ContentType).Boundary).Value;
 | ||
| 
 | ||
|             var reader = new MultipartReader(boundary, HttpContext.Request.Body);
 | ||
| 
 | ||
|             var section = await reader.ReadNextSectionAsync();
 | ||
| 
 | ||
|             while (section != null)
 | ||
|             {
 | ||
|                 var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
 | ||
| 
 | ||
|                 if (hasContentDispositionHeader)
 | ||
|                 {
 | ||
| 
 | ||
|                     var (serverFilePath, relativePath) = filePathFunc(contentDisposition.FileName.Value);
 | ||
| 
 | ||
|                     await FileStoreHelper.WriteFileAsync(section.Body, serverFilePath);
 | ||
| 
 | ||
|                     //仅仅返回一个文件,如果多文件上传  在最后返回多个路径
 | ||
|                     return ResponseOutput.Ok(new
 | ||
|                     {
 | ||
|                         FilePath = relativePath,
 | ||
|                         FullFilePath = relativePath /*+ "?access_token=" + _userInfo.UserToken*/
 | ||
|                     });
 | ||
| 
 | ||
|                 }
 | ||
|                 section = await reader.ReadNextSectionAsync();
 | ||
|             }
 | ||
|             return ResponseOutput.Ok();
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         /// <summary>  流式上传   通用封装 不返回任何数据,后续还有事情处理 </summary>
 | ||
|         [Route("base")]
 | ||
|         public virtual async Task FileUploadAsync(Func<string, Task<string>> filePathFunc)
 | ||
|         {
 | ||
|             var boundary = HeaderUtilities.RemoveQuotes(MediaTypeHeaderValue.Parse(Request.ContentType).Boundary).Value;
 | ||
| 
 | ||
|             var reader = new MultipartReader(boundary, HttpContext.Request.Body);
 | ||
| 
 | ||
|             var section = await reader.ReadNextSectionAsync();
 | ||
| 
 | ||
|             while (section != null)
 | ||
|             {
 | ||
|                 var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
 | ||
|                 if (hasContentDispositionHeader)
 | ||
|                 {
 | ||
|                     var fileName = contentDisposition.FileName.Value;
 | ||
|                     //处理压缩文件
 | ||
|                     if (fileName.Contains(".Zip", StringComparison.OrdinalIgnoreCase) || fileName.Contains(".rar", StringComparison.OrdinalIgnoreCase))
 | ||
|                     {
 | ||
|                         var archive = ArchiveFactory.Open(section.Body);
 | ||
| 
 | ||
|                         foreach (var entry in archive.Entries)
 | ||
|                         {
 | ||
|                             if (!entry.IsDirectory)
 | ||
|                             {
 | ||
|                                 var serverFilePath = await filePathFunc(entry.Key);
 | ||
|                                 entry.WriteToFile(serverFilePath);
 | ||
| 
 | ||
|                             }
 | ||
|                         }
 | ||
|                     }
 | ||
|                     //普通单个文件
 | ||
|                     else
 | ||
|                     {
 | ||
|                         var serverFilePath = await filePathFunc(fileName);
 | ||
| 
 | ||
|                         await FileStoreHelper.WriteFileAsync(section.Body, serverFilePath);
 | ||
|                     }
 | ||
| 
 | ||
|                 }
 | ||
|                 section = await reader.ReadNextSectionAsync();
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         /// <summary>  流式上传   Dicom上传  </summary>
 | ||
|         [Route("base")]
 | ||
|         public virtual async Task DicomFileUploadAsync(Func<string, Stream, int, Task> filePathFunc, string boundary)
 | ||
|         {
 | ||
| 
 | ||
|              var fileCount = 0;
 | ||
| 
 | ||
|                 var reader = new MultipartReader(boundary, HttpContext.Request.Body);
 | ||
| 
 | ||
|                 var section = await reader.ReadNextSectionAsync();
 | ||
| 
 | ||
|                 while (section != null)
 | ||
|                 {
 | ||
|                     var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
 | ||
| 
 | ||
|                     if (hasContentDispositionHeader)
 | ||
|                     {
 | ||
| 
 | ||
|                         var fileName = contentDisposition.FileName.Value ?? String.Empty;
 | ||
| 
 | ||
|                         string mediaType = section.ContentType ?? String.Empty;
 | ||
| 
 | ||
| 
 | ||
|                         //处理压缩文件
 | ||
|                         if (fileName.Contains(".Zip", StringComparison.OrdinalIgnoreCase) || fileName.Contains(".rar", StringComparison.OrdinalIgnoreCase))
 | ||
|                         {
 | ||
|                             var archive = ArchiveFactory.Open(section.Body);
 | ||
| 
 | ||
|                             foreach (var entry in archive.Entries)
 | ||
|                             {
 | ||
|                                 if (!entry.IsDirectory)
 | ||
|                                 {
 | ||
|                                     ++fileCount;
 | ||
| 
 | ||
|                                     await filePathFunc(entry.Key, entry.OpenEntryStream(), fileCount);
 | ||
|                                 }
 | ||
|                             }
 | ||
|                         }
 | ||
|                         //普通单个文件
 | ||
|                         else
 | ||
|                         {
 | ||
|                             if (mediaType.Contains("octet-stream") || mediaType.Contains("dicom"))
 | ||
|                             {
 | ||
|                                 ++fileCount;
 | ||
| 
 | ||
|                                 await filePathFunc(fileName, section.Body, fileCount);
 | ||
|                             }
 | ||
| 
 | ||
|                         }
 | ||
|                     }
 | ||
|                     section = await reader.ReadNextSectionAsync();
 | ||
|                 }
 | ||
|      
 | ||
| 
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
|     #endregion
 | ||
| 
 | ||
|     #region Dicom 影像上传  临床数据  非diocm 
 | ||
| 
 | ||
|     [ApiExplorerSettings(GroupName = "Image")]
 | ||
|     [ApiController]
 | ||
|     public class StudyController : UploadBaseController
 | ||
|     {
 | ||
|         public IMapper _mapper { get; set; }
 | ||
|         public IUserInfo _userInfo { get; set; }
 | ||
|         private readonly IMediator _mediator;
 | ||
| 
 | ||
|         private readonly IWebHostEnvironment _hostEnvironment;
 | ||
| 
 | ||
|         private readonly IRepository _repository;
 | ||
| 
 | ||
|         private readonly IEasyCachingProvider _provider;
 | ||
| 
 | ||
|         public StudyController(IMapper mapper, IUserInfo userInfo, IWebHostEnvironment hostEnvironment, IMediator mediator, IEasyCachingProvider provider,
 | ||
| 
 | ||
|             IRepository repository)
 | ||
|         {
 | ||
|             _provider = provider;
 | ||
|             _hostEnvironment = hostEnvironment;
 | ||
|             _mediator = mediator;
 | ||
| 
 | ||
|             _mapper = mapper;
 | ||
|             _userInfo = userInfo;
 | ||
|             _repository = repository;
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         /// <summary>Dicom 归档</summary>
 | ||
|         [HttpPost, Route("Study/ArchiveStudy")]
 | ||
|         [DisableFormValueModelBinding]
 | ||
|         [DisableRequestSizeLimit]
 | ||
|          [TypeFilter(typeof(TrialResourceFilter),Arguments = new object[] { "AfterStopCannNotOpt" })]
 | ||
|         public async Task<IResponseOutput> ArchiveStudyNew(/*[FromForm] ArchiveStudyCommand archiveStudyCommand,*/ Guid trialId, Guid subjectVisitId, string studyInstanceUid, Guid? abandonStudyId,
 | ||
|              [FromServices] ILogger<UploadDownLoadController> _logger,
 | ||
|              [FromServices] IEasyCachingProvider _provider,
 | ||
|              [FromServices] IStudyService _studyService,
 | ||
|              [FromServices] IHubContext<UploadHub, IUploadClient> _uploadHub,
 | ||
|              [FromServices] IDicomArchiveService _dicomArchiveService,
 | ||
|              [FromServices] IRepository _repository
 | ||
|             )
 | ||
|         {
 | ||
| 
 | ||
| 
 | ||
|             if (_provider.Get<List<SystemAnonymization>>(StaticData.Anonymize.Anonymize_AddFixedFiled).Value==null  )
 | ||
|             {
 | ||
|                 await _mediator.Send(new AnonymizeCacheRequest());
 | ||
|             }
 | ||
| 
 | ||
|             //_logger.LogError("请求到达接口");
 | ||
| 
 | ||
|             if (!HttpContext.Request.HasFormContentType ||
 | ||
|                 !MediaTypeHeaderValue.TryParse(HttpContext.Request.ContentType, out var mediaTypeHeader) ||
 | ||
|                 string.IsNullOrEmpty(mediaTypeHeader.Boundary.Value))
 | ||
|             {
 | ||
|                 return ResponseOutput.NotOk("不支持的MediaType");
 | ||
|             }
 | ||
| 
 | ||
|             var archiveStudyCommand = new ArchiveStudyCommand() { AbandonStudyId = abandonStudyId, StudyInstanceUid = studyInstanceUid, SubjectVisitId = subjectVisitId };
 | ||
| 
 | ||
| 
 | ||
|             string studycode = string.Empty;
 | ||
| 
 | ||
|             var startTime = DateTime.Now;
 | ||
| 
 | ||
|             if (_provider.Exists($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}" ))
 | ||
|             {
 | ||
|                 return ResponseOutput.NotOk("当前已有人正在上传和归档该检查!");
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 _provider.Set($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}", _userInfo.Id, TimeSpan.FromMinutes(30));
 | ||
|             }
 | ||
| 
 | ||
|             var (archiveResult, archivedStudyIds) = (new DicomArchiveResult(), new List<Guid>());
 | ||
| 
 | ||
| 
 | ||
|             var (seriesInstanceUidList, sopInstanceUidList) = (new List<string>(), new List<string>());
 | ||
| 
 | ||
|             //重传的时候,找出当前检查已经上传的series instance
 | ||
|             if (archiveStudyCommand.AbandonStudyId != null)
 | ||
|             {
 | ||
|                 (seriesInstanceUidList, sopInstanceUidList) = _studyService.GetHasUploadSeriesAndInstance(archiveStudyCommand.AbandonStudyId.Value);
 | ||
|             }
 | ||
| 
 | ||
|             var savedInfo = _studyService.GetSaveToDicomInfo(archiveStudyCommand.SubjectVisitId);
 | ||
| 
 | ||
|             try
 | ||
|             {
 | ||
| 
 | ||
|                 await DicomFileUploadAsync(async (fileName, fileStream, receivedCount) =>
 | ||
|                 {
 | ||
| 
 | ||
|                     try
 | ||
|                     {
 | ||
|                         using (var memoryStream = new MemoryStream())
 | ||
|                         {
 | ||
|                             await fileStream.CopyToAsync(memoryStream);
 | ||
| 
 | ||
|                             memoryStream.Seek(0, SeekOrigin.Begin);
 | ||
| 
 | ||
|                             var (studyId, studyCode) = await _dicomArchiveService.ArchiveDicomStreamAsync(memoryStream, savedInfo, seriesInstanceUidList, sopInstanceUidList);
 | ||
|                             if (!archivedStudyIds.Contains(studyId))
 | ||
|                             {
 | ||
|                                 archivedStudyIds.Add(studyId);
 | ||
|                                 archiveResult.ArchivedDicomStudies.Add(new DicomStudyBasicDTO() { StudyCode = studyCode, Id = studyId });
 | ||
|                             }
 | ||
|                         }
 | ||
| 
 | ||
|                         //await _uploadHub.Clients.All.ReceivProgressAsync(archiveStudyCommand.StudyInstanceUid, receivedCount);
 | ||
| 
 | ||
| 
 | ||
|                         await _uploadHub.Clients.User(_userInfo.Id.ToString()).ReceivProgressAsync(archiveStudyCommand.StudyInstanceUid, receivedCount);
 | ||
| 
 | ||
|                         archiveResult.ReceivedFileCount = receivedCount;
 | ||
| 
 | ||
|                     }
 | ||
|                     catch (Exception e)
 | ||
|                     {
 | ||
|                         _logger.LogError(e.Message + e.StackTrace);
 | ||
| 
 | ||
|                         archiveResult.ErrorFiles.Add(fileName);
 | ||
|                     }
 | ||
| 
 | ||
| 
 | ||
|                 }, mediaTypeHeader.Boundary.Value);
 | ||
| 
 | ||
| 
 | ||
|             }
 | ||
|             catch (Exception ex)
 | ||
|             {
 | ||
|                 _provider.Remove($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}");
 | ||
| 
 | ||
|                 throw new BusinessValidationFailedException("请求异常,请重试!");
 | ||
|             }
 | ||
| 
 | ||
| 
 | ||
|             var studyMonitor = new StudyMonitor()
 | ||
|             {
 | ||
|                 TrialId = savedInfo.TrialId,
 | ||
|                 SiteId = savedInfo.SiteId,
 | ||
|                 SubjectId = savedInfo.SubjectId,
 | ||
|                 SubjectVisitId = savedInfo.SubjectVisitId,
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|                 UploadStartTime = startTime,
 | ||
|                 FileSize = (decimal)HttpContext.Request.ContentLength,
 | ||
|                 FileCount = archiveResult.ReceivedFileCount,
 | ||
|                 IsDicom = true,
 | ||
|                 IsDicomReUpload = archiveStudyCommand.AbandonStudyId != null,
 | ||
|                 IP = _userInfo.IP
 | ||
|             };
 | ||
| 
 | ||
|             try
 | ||
|             {
 | ||
| 
 | ||
|                 if (archivedStudyIds.Count > 0) // 上传成功,处理逻辑
 | ||
|                 {
 | ||
| 
 | ||
|                     // 同一个访视 多个线程上传处理  批量保存 可能造成死锁 https://www.cnblogs.com/johnblogs/p/9945767.html
 | ||
| 
 | ||
|                     await _dicomArchiveService.DicomDBDataSaveChange();
 | ||
| 
 | ||
|                     archiveResult.ReuploadNewStudyId = archivedStudyIds[0] == archiveStudyCommand.AbandonStudyId ? archivedStudyIds[0] : Guid.Empty;
 | ||
| 
 | ||
|                     studyMonitor.IsSuccess = true;
 | ||
| 
 | ||
|                 }
 | ||
|                 else
 | ||
|                 {
 | ||
|                     studyMonitor.IsSuccess = false;
 | ||
|                     studyMonitor.Note = JsonConvert.SerializeObject(archiveResult);                 
 | ||
|                 }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|             }
 | ||
|             catch (Exception e)
 | ||
|             {
 | ||
| 
 | ||
|                 studyMonitor.IsSuccess = false;
 | ||
|                 studyMonitor.Note = JsonConvert.SerializeObject(new { Message = e.Message, Result = archiveResult });
 | ||
| 
 | ||
|                 _logger.LogError(e.Message + e.StackTrace);
 | ||
| 
 | ||
|             }
 | ||
|             finally
 | ||
|             {
 | ||
|                 _provider.Remove($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}");
 | ||
| 
 | ||
|                 studyMonitor.StudyId = archiveResult.ArchivedDicomStudies.FirstOrDefault()?.Id ?? Guid.Empty;
 | ||
|                 studyMonitor.StudyCode = archiveResult.ArchivedDicomStudies.FirstOrDefault()?.StudyCode;
 | ||
|                 studyMonitor.UploadFinishedTime = DateTime.Now;
 | ||
|                 await _repository.AddAsync(studyMonitor, true);
 | ||
| 
 | ||
|             }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|             return ResponseOutput.Result(studyMonitor.IsSuccess, archiveResult);
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 上传临床数据  多文件
 | ||
|         /// </summary>
 | ||
|         /// <param name="subjectVisitId"></param>
 | ||
|         /// <returns></returns>
 | ||
|         [HttpPost("ClinicalData/UploadVisitClinicalData/{trialId:guid}/{subjectVisitId:guid}")]
 | ||
|         [DisableRequestSizeLimit]
 | ||
|         [Authorize(Policy = IRaCISPolicy.CRC)]
 | ||
|         public async Task<IResponseOutput> UploadVisitClinicalData(Guid subjectVisitId)
 | ||
|         {
 | ||
|             await QCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId);
 | ||
|             var sv = _repository.Where<SubjectVisit>(t => t.Id == subjectVisitId).Select(t => new { t.TrialId, t.SiteId, t.SubjectId }).FirstOrDefault().IfNullThrowException();
 | ||
| 
 | ||
|             await FileUploadAsync(async (fileName) =>
 | ||
|             {
 | ||
|                 var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetClinicalDataPath(_hostEnvironment, fileName, sv.TrialId, sv.SiteId, sv.SubjectId, subjectVisitId);
 | ||
|                 //插入临床pdf 路径
 | ||
|                 await _repository.AddAsync(new PreviousPDF()
 | ||
|                 {
 | ||
|                     SubjectVisitId = subjectVisitId,
 | ||
| 
 | ||
|                     IsVisist = true,
 | ||
|                     DataType = ClinicalDataType.MedicalHistory,
 | ||
|                     UploadType = ClinicalUploadType.PDF,
 | ||
|                     SubjectId = sv.SubjectId,
 | ||
|                     TrialId = sv.TrialId,
 | ||
|                     ClinicalLevel = ClinicalLevel.Subject,
 | ||
|                     Path = relativePath,
 | ||
|                     FileName = fileRealName
 | ||
|                 });
 | ||
|                 return serverFilePath;
 | ||
|             });
 | ||
|             await _repository.SaveChangesAsync();
 | ||
|             return ResponseOutput.Ok();
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 上传临床数据模板
 | ||
|         /// </summary>
 | ||
|         /// <param name="trialId"></param>
 | ||
|         /// <returns></returns>
 | ||
|         [HttpPost("ClinicalData/UploadClinicalTemplate")]
 | ||
|         [DisableRequestSizeLimit]
 | ||
| 
 | ||
|         public async Task<IResponseOutput<List<FileDto>>> UploadClinicalTemplate(Guid? trialId)
 | ||
|         {
 | ||
|             if (trialId == null)
 | ||
|                 trialId = default(Guid);
 | ||
| 
 | ||
|             var filerelativePath = string.Empty;
 | ||
|             List<FileDto> fileDtos = new List<FileDto>();
 | ||
|             await FileUploadAsync(async (fileName) =>
 | ||
|             {
 | ||
|                 var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetClinicalTemplatePath(_hostEnvironment, fileName, trialId.Value);
 | ||
|                 //插入临床pdf 路径
 | ||
|                 filerelativePath = relativePath;
 | ||
| 
 | ||
|                 fileDtos.Add(new FileDto()
 | ||
|                 {
 | ||
|                     FileName = fileName,
 | ||
|                     Path = relativePath
 | ||
| 
 | ||
|                 });
 | ||
|                 await Task.CompletedTask;
 | ||
|                 return serverFilePath;
 | ||
|             });
 | ||
| 
 | ||
|             return ResponseOutput.Ok(fileDtos);
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 上传阅片临床数据
 | ||
|         /// </summary>
 | ||
|         /// <param name="trialId"></param>
 | ||
|         /// <param name="subjectId"></param>
 | ||
|         /// <param name="readingId"></param>
 | ||
|         /// <returns></returns>
 | ||
|         [HttpPost("ClinicalData/UploadClinicalData/{trialId:guid}/{subjectId:guid}/{readingId:guid}")]
 | ||
|         [DisableRequestSizeLimit]
 | ||
|         public async Task<IResponseOutput<List<FileDto>>> UploadReadClinicalData(Guid trialId, Guid subjectId, Guid readingId)
 | ||
|         {
 | ||
|             var filerelativePath = string.Empty;
 | ||
|             List<FileDto> fileDtos = new List<FileDto>();
 | ||
| 
 | ||
|             var siteid = await _repository.Where<Subject>(x => x.Id == subjectId).Select(x => x.SiteId).FirstOrDefaultAsync();
 | ||
| 
 | ||
|             await FileUploadAsync(async (fileName) =>
 | ||
|              {
 | ||
|                  var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetReadClinicalDataPath(_hostEnvironment, fileName, trialId, siteid, subjectId, readingId);
 | ||
|                  //插入临床pdf 路径
 | ||
|                  filerelativePath = relativePath;
 | ||
| 
 | ||
|                  fileDtos.Add(new FileDto()
 | ||
|                  {
 | ||
|                      FileName = fileName,
 | ||
|                      Path = relativePath
 | ||
| 
 | ||
|                  });
 | ||
|                  await Task.CompletedTask;
 | ||
|                  return serverFilePath;
 | ||
|              });
 | ||
| 
 | ||
|             return ResponseOutput.Ok(fileDtos);
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 上传Reading问题的图像
 | ||
|         /// </summary>
 | ||
|         /// <param name="trialId"></param>
 | ||
|         /// <param name="visitTaskId"></param>
 | ||
|         /// <returns></returns>
 | ||
|         [HttpPost("VisitTask/UploadReadingAnswerImage/{trialId:guid}/{visitTaskId:guid}")]
 | ||
|          [TypeFilter(typeof(TrialResourceFilter),Arguments = new object[] { "AfterStopCannNotOpt" })]
 | ||
|         public async Task<IResponseOutput<FileDto>> UploadReadingAnswerImage(Guid trialId, Guid visitTaskId)
 | ||
|         {
 | ||
| 
 | ||
|             FileDto fileDto = new FileDto();
 | ||
|             await FileUploadAsync(async (fileName) =>
 | ||
|             {
 | ||
|                 var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetFilePath(_hostEnvironment, fileName, trialId, visitTaskId, StaticData.Folder.JudgeTask);
 | ||
|                 fileDto.Path = relativePath;
 | ||
|                 fileDto.FileName = fileName;
 | ||
|                 await Task.CompletedTask;
 | ||
|                 return serverFilePath;
 | ||
|             });
 | ||
| 
 | ||
| 
 | ||
|             return ResponseOutput.Ok(fileDto);
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 上传裁判任务的图像
 | ||
|         /// </summary>
 | ||
|         /// <param name="trialId"></param>
 | ||
|         /// <param name="visitTaskId"></param>
 | ||
|         /// <returns></returns>
 | ||
|         [HttpPost("VisitTask/UploadJudgeTaskImage/{trialId:guid}/{visitTaskId:guid}")]
 | ||
|          [TypeFilter(typeof(TrialResourceFilter),Arguments = new object[] { "AfterStopCannNotOpt" })]
 | ||
|         public async Task<IResponseOutput<FileDto>> UploadJudgeTaskImage(Guid trialId, Guid visitTaskId)
 | ||
|         {
 | ||
| 
 | ||
|             FileDto fileDto = new FileDto();
 | ||
|             await FileUploadAsync(async (fileName) =>
 | ||
|             {
 | ||
|                 var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetFilePath(_hostEnvironment, fileName, trialId, visitTaskId, StaticData.Folder.JudgeTask);
 | ||
|                 fileDto.Path = relativePath;
 | ||
|                 fileDto.FileName = fileName;
 | ||
| 
 | ||
|                 await Task.CompletedTask;
 | ||
| 
 | ||
|                 return serverFilePath;
 | ||
|             });
 | ||
| 
 | ||
|             return ResponseOutput.Ok(fileDto);
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 上传医学审核图片
 | ||
|         /// </summary>
 | ||
|         /// <param name="trialId"></param>
 | ||
|         /// <param name="taskMedicalReviewId"></param>
 | ||
|         /// <returns></returns>
 | ||
|         [HttpPost("TaskMedicalReview/UploadMedicalReviewImage/{trialId:guid}/{taskMedicalReviewId:guid}")]
 | ||
|          [TypeFilter(typeof(TrialResourceFilter),Arguments = new object[] { "AfterStopCannNotOpt" })]
 | ||
|         public async Task<IResponseOutput<FileDto>> UploadMedicalReviewImage(Guid trialId, Guid taskMedicalReviewId)
 | ||
|         {
 | ||
|             string path = string.Empty;
 | ||
|             FileDto fileDto = new FileDto();
 | ||
|             await FileUploadAsync(async (fileName) =>
 | ||
|             {
 | ||
| 
 | ||
|                 var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetMedicalReviewImage(_hostEnvironment, fileName, trialId, taskMedicalReviewId);
 | ||
| 
 | ||
| 
 | ||
|                 //await _repository.UpdatePartialFromQueryAsync<TaskMedicalReview>(x => x.Id == taskMedicalReviewId, x => new TaskMedicalReview()
 | ||
|                 //{
 | ||
|                 //    ImagePath = relativePath,
 | ||
|                 //    FileName = fileName,
 | ||
|                 //});
 | ||
| 
 | ||
|                 path = relativePath;
 | ||
|                 fileDto.Path = relativePath;
 | ||
|                 fileDto.FileName = fileName;
 | ||
|                 return serverFilePath;
 | ||
|             });
 | ||
| 
 | ||
|             await _repository.SaveChangesAsync();
 | ||
|             return ResponseOutput.Ok(fileDto);
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 上传非Dicom 文件 支持压缩包 多文件上传
 | ||
|         /// </summary>
 | ||
|         /// <param name="formCollection"></param>
 | ||
|         /// <param name="subjectVisitId"></param>
 | ||
|         /// <param name="noneDicomStudyId"></param>
 | ||
|         /// <returns></returns>
 | ||
|         //[DisableRequestSizeLimit]
 | ||
|         [RequestSizeLimit(1_073_741_824)]
 | ||
|         [HttpPost("NoneDicomStudy/UploadNoneDicomFile/{trialId:guid}/{subjectVisitId:guid}/{noneDicomStudyId:guid}")]
 | ||
|          [TypeFilter(typeof(TrialResourceFilter),Arguments = new object[] { "AfterStopCannNotOpt" })]
 | ||
|         [Authorize(Policy = IRaCISPolicy.CRC)]
 | ||
|         public async Task<IResponseOutput> UploadNoneDicomFile(IFormCollection formCollection, Guid subjectVisitId, Guid noneDicomStudyId, [FromServices] IRepository<NoneDicomStudy> _noneDicomStudyRepository)
 | ||
|         {
 | ||
|             var startTime = DateTime.Now;
 | ||
| 
 | ||
|             await QCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId);
 | ||
| 
 | ||
|             var sv = (await _repository.Where<SubjectVisit>(t => t.Id == subjectVisitId).Select(t => new { t.TrialId, t.SiteId, t.SubjectId }).FirstOrDefaultAsync()).IfNullThrowConvertException();
 | ||
| 
 | ||
| 
 | ||
|             await FileUploadAsync(async (fileName) =>
 | ||
|             {
 | ||
| 
 | ||
|                 var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetNoneDicomFilePath(_hostEnvironment, fileName, sv.TrialId, sv.SiteId, sv.SubjectId, subjectVisitId);
 | ||
| 
 | ||
|                 await _repository.AddAsync(new NoneDicomStudyFile() { FileName = fileRealName, Path = relativePath, NoneDicomStudyId = noneDicomStudyId });
 | ||
| 
 | ||
|                 return serverFilePath;
 | ||
|             });
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|             //// 上传非Dicom 后  将状态改为待提交 分为普通上传 和QC后重传  普通上传时才改为待提交
 | ||
|             //await _repository.UpdatePartialFromQueryAsync<SubjectVisit>(t => t.Id == subjectVisitId && t.SubmitState == SubmitStateEnum.None, u => new SubjectVisit() { SubmitState = SubmitStateEnum.ToSubmit });
 | ||
| 
 | ||
|             var noneDicomStudy = await _noneDicomStudyRepository.FirstOrDefaultAsync((t => t.Id == noneDicomStudyId));
 | ||
| 
 | ||
|             noneDicomStudy.FileCount = noneDicomStudy.FileCount + formCollection.Files.Count;
 | ||
| 
 | ||
|             await _repository.AddAsync(new StudyMonitor()
 | ||
|             {
 | ||
|                 FileCount = formCollection.Files.Count,
 | ||
|                 FileSize = formCollection.Files.Sum(t => t.Length),
 | ||
|                 IsDicom = false,
 | ||
|                 IsDicomReUpload = false,
 | ||
|                 StudyId = noneDicomStudyId,
 | ||
|                 StudyCode = noneDicomStudy.StudyCode,
 | ||
|                 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();
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 一致性核查 excel上传 支持三种格式
 | ||
|         /// </summary>
 | ||
|         /// <param name="trialId"></param>
 | ||
|         /// <returns></returns>
 | ||
|         [HttpPost("QCOperation/UploadVisitCheckExcel/{trialId:guid}")]
 | ||
|          [TypeFilter(typeof(TrialResourceFilter),Arguments = new object[] { "AfterStopCannNotOpt" })]
 | ||
|         [Authorize(Policy = IRaCISPolicy.PM_APM)]
 | ||
|         public async Task<IResponseOutput> UploadVisitCheckExcel(Guid trialId)
 | ||
|         {
 | ||
| 
 | ||
|             var (serverFilePath, relativePath, fileName) = (string.Empty, string.Empty, string.Empty);
 | ||
|             await FileUploadAsync(async (realFileName) =>
 | ||
|             {
 | ||
|                 fileName = realFileName;
 | ||
| 
 | ||
|                 if (!fileName.EndsWith(".xlsx") && !fileName.EndsWith(".csv") && !fileName.EndsWith(".xls"))
 | ||
|                 {
 | ||
|                     throw new BusinessValidationFailedException("支持.xlsx、.xls、.csv格式的文件上传。");
 | ||
|                 }
 | ||
| 
 | ||
|                 (serverFilePath, relativePath) = FileStoreHelper.GetTrialCheckFilePath(_hostEnvironment, fileName, trialId);
 | ||
| 
 | ||
|                 await _repository.AddAsync(new ConsistencyCheckFile()
 | ||
|                 {
 | ||
|                     TrialId = trialId,
 | ||
|                     CreateTime = DateTime.Now,
 | ||
|                     FileName = fileName,
 | ||
|                     FilePath = relativePath,
 | ||
|                     RelativePath = relativePath,
 | ||
|                     CreateUserId = _userInfo.Id
 | ||
|                 });
 | ||
| 
 | ||
|                 return serverFilePath;
 | ||
|             });
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|             var etcCheckList = new List<CheckViewModel>();
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|             #region MiniExcel  需要自己验证数据格式规范
 | ||
| 
 | ||
|             //if (fileName.EndsWith(".csv"))
 | ||
|             //{
 | ||
|             //    //因为csv 需要加配置文件 不然都是null
 | ||
|             //    etcCheckList = MiniExcel.Query<CheckViewModel>(filePath, null, configuration: config).ToList();
 | ||
|             //}
 | ||
|             //else if (fileName.EndsWith(".xlsx"))
 | ||
|             //{
 | ||
|             //    
 | ||
| 
 | ||
| 
 | ||
|             //    etcCheckList = MiniExcel.Query<CheckViewModel>(filePath).ToList();
 | ||
|             //}
 | ||
| 
 | ||
|             #endregion
 | ||
| 
 | ||
|             //Magicodes 支持自定义特性验证
 | ||
|             if (fileName.EndsWith(".xlsx"))
 | ||
|             {
 | ||
|                 var Importer = new ExcelImporter();
 | ||
| 
 | ||
|                 var import = await Importer.Import<CheckViewModel>(System.IO.File.OpenRead(serverFilePath));
 | ||
| 
 | ||
|                 if (import.Exception != null) return ResponseOutput.NotOk(import.Exception.ToString());
 | ||
| 
 | ||
|                 if (import.RowErrors.Count > 0) return ResponseOutput.NotOk(JsonConvert.SerializeObject(import.RowErrors));
 | ||
| 
 | ||
|                 if (import.TemplateErrors.Count > 0) return ResponseOutput.NotOk(JsonConvert.SerializeObject(import.TemplateErrors));
 | ||
| 
 | ||
|                 etcCheckList = import.Data.ToList();
 | ||
|             }
 | ||
|             else if (fileName.EndsWith(".csv"))
 | ||
|             {
 | ||
|                 #region   临时方案   MiniExcel读取  然后保存为xlsx  再用 Magicodes验证数据
 | ||
| 
 | ||
|                 //因为csv 需要加配置文件 不然都是null
 | ||
|                 etcCheckList = MiniExcel.Query<CheckViewModel>(serverFilePath, null, configuration: new MiniExcelLibs.Csv.CsvConfiguration()
 | ||
|                 {
 | ||
|                     StreamReaderFunc = (stream) => new StreamReader(stream, Encoding.GetEncoding("gb2312"))
 | ||
|                 }).ToList();
 | ||
| 
 | ||
|                 var (csVToXlsxPath, csVToXlsxRelativePath) = FileStoreHelper.GetTrialCheckFilePath(_hostEnvironment, Path.GetFileNameWithoutExtension(fileName) + ".xlsx", trialId);
 | ||
| 
 | ||
| 
 | ||
|                 await MiniExcel.SaveAsAsync(csVToXlsxPath, etcCheckList, excelType: ExcelType.XLSX);
 | ||
| 
 | ||
| 
 | ||
|                 var Importer = new ExcelImporter();
 | ||
| 
 | ||
|                 var import = await Importer.Import<CheckViewModel>(System.IO.File.OpenRead(csVToXlsxPath));
 | ||
| 
 | ||
|                 if (import.Exception != null) return ResponseOutput.NotOk(import.Exception.ToString());
 | ||
| 
 | ||
|                 if (import.RowErrors.Count > 0) return ResponseOutput.NotOk(JsonConvert.SerializeObject(import.RowErrors));
 | ||
| 
 | ||
|                 if (import.TemplateErrors.Count > 0) return ResponseOutput.NotOk(JsonConvert.SerializeObject(import.TemplateErrors));
 | ||
| 
 | ||
|                 etcCheckList = import.Data.ToList();
 | ||
| 
 | ||
|                 #endregion
 | ||
| 
 | ||
| 
 | ||
|                 #region 导入组件有问题  excel编码格式
 | ||
|                 //var Importer = new CsvImporter();
 | ||
| 
 | ||
|                 //var import = await Importer.Import<CheckViewModel>(File.OpenRead(filePath));
 | ||
| 
 | ||
|                 //if (import.Exception != null) return ResponseOutput.NotOk(import.Exception.ToString());
 | ||
| 
 | ||
|                 //if (import.RowErrors.Count > 0) return ResponseOutput.NotOk(JsonConvert.SerializeObject(import.RowErrors));
 | ||
| 
 | ||
|                 //if (import.TemplateErrors.Count > 0) return ResponseOutput.NotOk(JsonConvert.SerializeObject(import.TemplateErrors));
 | ||
| 
 | ||
|                 //etcCheckList = import.Data.ToList();
 | ||
|                 #endregion
 | ||
| 
 | ||
|             }
 | ||
|             //ExcelReaderFactory  需要自己验证数据 并且从固定列取数据
 | ||
|             else
 | ||
|             {
 | ||
|                 //为了支持 xls  引入新的组件库
 | ||
|                 using (var stream = System.IO.File.Open(serverFilePath, FileMode.Open, FileAccess.Read))
 | ||
|                 {
 | ||
|                     // Auto-detect format, supports:
 | ||
|                     //  - Binary Excel files (2.0-2003 format; *.xls)
 | ||
|                     //  - OpenXml Excel files (2007 format; *.xlsx, *.xlsb)
 | ||
|                     using (var reader = ExcelReaderFactory.CreateReader(stream))
 | ||
|                     {
 | ||
| 
 | ||
|                         // 2. Use the AsDataSet extension method
 | ||
|                         var dateset = reader.AsDataSet();
 | ||
| 
 | ||
|                         foreach (DataRow col in dateset.Tables[0].Rows)
 | ||
|                         {
 | ||
| 
 | ||
|                             etcCheckList.Add(new CheckViewModel()
 | ||
|                             {
 | ||
|                                 SiteCode = col[0].ToString(),
 | ||
|                                 SubjectCode = col[1].ToString(),
 | ||
|                                 VisitName = col[2].ToString(),
 | ||
|                                 StudyDate = col[3].ToString(),
 | ||
|                                 Modality = col[4].ToString(),
 | ||
|                             });
 | ||
|                         }
 | ||
| 
 | ||
|                         etcCheckList.Remove(etcCheckList[0]);
 | ||
| 
 | ||
|                         // The result of each spreadsheet is in result.Tables
 | ||
|                     }
 | ||
|                 }
 | ||
|             }
 | ||
| 
 | ||
|             if (etcCheckList == null || etcCheckList.Count == 0)
 | ||
|             {
 | ||
|                 return ResponseOutput.NotOk("请保证上传数据符合模板文件中的样式,且存在有效数据。");
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 //处理Excel  有时只是清除某些行的数据  读取也会读到数据,只是数据是null   后面处理的时候转为字符串为报错
 | ||
|                 etcCheckList.ForEach(t =>
 | ||
|                 {
 | ||
|                     t.Modality = t.Modality ?? string.Empty;
 | ||
|                     t.SiteCode = t.SiteCode ?? string.Empty;
 | ||
|                     t.SubjectCode = t.SubjectCode ?? string.Empty;
 | ||
|                     t.VisitName = t.VisitName ?? string.Empty;
 | ||
|                     t.StudyDate = t.StudyDate ?? string.Empty;
 | ||
|                 });
 | ||
| 
 | ||
|                 var dt = DateTime.Now;
 | ||
| 
 | ||
|                 etcCheckList = etcCheckList.Where(t => !(t.Modality == string.Empty && t.SiteCode == string.Empty && t.SubjectCode == string.Empty && t.VisitName == string.Empty && t.StudyDate == string.Empty && DateTime.TryParse(t.StudyDate, out dt))).ToList();
 | ||
| 
 | ||
|                 if (etcCheckList.Count == 0)
 | ||
|                 {
 | ||
|                     return ResponseOutput.NotOk("请保证上传数据符合模板文件中的样式,且存在有效数据。");
 | ||
|                 }
 | ||
| 
 | ||
|             }
 | ||
| 
 | ||
| 
 | ||
|             await _mediator.Send(new ConsistencyVerificationRequest() { ETCList = etcCheckList, TrialId = trialId });
 | ||
| 
 | ||
|             return ResponseOutput.Ok();
 | ||
| 
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     #endregion
 | ||
| 
 | ||
|     #region 医生文件上传下载
 | ||
| 
 | ||
|     /// <summary>医生文件上传下载</summary>
 | ||
|     [ApiExplorerSettings(GroupName = "Common")]
 | ||
|     [ApiController]
 | ||
|     public class FileController : UploadBaseController
 | ||
|     {
 | ||
|         public IMapper _mapper { get; set; }
 | ||
|         public IUserInfo _userInfo { get; set; }
 | ||
| 
 | ||
| 
 | ||
|         private readonly IWebHostEnvironment _hostEnvironment;
 | ||
| 
 | ||
|         private readonly IFileService _fileService;
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         public FileController(IMapper mapper, IUserInfo userInfo, IWebHostEnvironment hostEnvironment, IFileService fileService)
 | ||
|         {
 | ||
|             _fileService = fileService;
 | ||
|             _hostEnvironment = hostEnvironment;
 | ||
| 
 | ||
|             _mapper = mapper;
 | ||
|             _userInfo = userInfo;
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 上传文件[FileUpload]
 | ||
|         /// </summary>
 | ||
|         /// <param name="attachmentType">附件类型</param>
 | ||
|         /// <param name="doctorId">医生Id</param>
 | ||
|         /// <returns>返回文件信息</returns>
 | ||
|         [HttpPost, Route("file/UploadFile/{attachmentType}/{doctorId}")]
 | ||
|         [DisableFormValueModelBinding]
 | ||
|         [DisableRequestSizeLimit]
 | ||
|         public async Task<IResponseOutput> UploadOrdinaryFile(string attachmentType, Guid doctorId)
 | ||
|         {
 | ||
| 
 | ||
|             return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetDoctorOrdinaryFilePath(_hostEnvironment, fileName, doctorId, attachmentType));
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 上传文件( 不是医生个人的文件)[FileUpload]
 | ||
|         /// 例如:阅片章程等
 | ||
|         /// </summary>
 | ||
|         /// <param name="type">文件类型</param>
 | ||
|         /// <returns></returns>
 | ||
| 
 | ||
|         [HttpPost, Route("file/UploadNonDoctorFile/{type}")]
 | ||
|         [DisableFormValueModelBinding]
 | ||
|         [DisableRequestSizeLimit]
 | ||
|         public async Task<IResponseOutput> UploadNonDoctorFile(string type)
 | ||
|         {
 | ||
|             return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetNonDoctorFilePath(_hostEnvironment, fileName, type));
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 下载多个医生的所有附件
 | ||
|         /// </summary>
 | ||
|         /// <param name="doctorIds"></param>
 | ||
|         /// <returns></returns>
 | ||
| 
 | ||
|         [HttpPost, Route("file/downloadDoctorAttachments")]
 | ||
|         public async Task<IResponseOutput<UploadFileInfoDTO>> DownloadAttachment(Guid[] doctorIds)
 | ||
|         {
 | ||
| 
 | ||
|             var path = await _fileService.CreateDoctorsAllAttachmentZip(doctorIds);
 | ||
| 
 | ||
|             return ResponseOutput.Ok(new UploadFileInfoDTO
 | ||
|             {
 | ||
|                 FilePath = path,
 | ||
|                 FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7)
 | ||
| 
 | ||
|             });
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 下载医生官方简历
 | ||
|         /// </summary>
 | ||
|         /// <param name="language"></param>
 | ||
|         /// <param name="doctorIds"></param>
 | ||
|         /// <returns></returns>
 | ||
|         [HttpPost, Route("file/downloadOfficialCV/{language}")]
 | ||
|         public async Task<IResponseOutput<UploadFileInfoDTO>> DownloadOfficialResume(int language, Guid[] doctorIds)
 | ||
|         {
 | ||
| 
 | ||
|             var path = await  _fileService.CreateDoctorsAllAttachmentZip(doctorIds);
 | ||
|             return ResponseOutput.Ok(new UploadFileInfoDTO
 | ||
|             {
 | ||
|                 FilePath = await _fileService.CreateOfficialResumeZip(language, doctorIds),
 | ||
|                 FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7)
 | ||
|             });
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 下载指定医生的指定附件
 | ||
|         /// </summary>
 | ||
|         /// <param name="doctorId">医生Id</param>
 | ||
|         /// <param name="attachmentIds">要下载的附件Id</param>
 | ||
|         /// <returns></returns>
 | ||
|         [HttpPost, Route("file/downloadByAttachmentId/{doctorId}")]
 | ||
|         public async Task<IResponseOutput<UploadFileInfoDTO>> DownloadAttachmentById(Guid doctorId, Guid[] attachmentIds)
 | ||
|         {
 | ||
|             var path = await _fileService.CreateZipPackageByAttachment(doctorId, attachmentIds);
 | ||
|             return ResponseOutput.Ok(new UploadFileInfoDTO
 | ||
|             {
 | ||
|                 FilePath = await _fileService.CreateZipPackageByAttachment(doctorId, attachmentIds),
 | ||
|                 FullFilePath = path + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7)
 | ||
|             });
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         [HttpPost, Route("enroll/downloadResume/{trialId:guid}/{language}")]
 | ||
|          [TypeFilter(typeof(TrialResourceFilter),Arguments = new object[] { "AfterStopCannNotOpt" })]
 | ||
|         [AllowAnonymous]
 | ||
|         public async Task<IResponseOutput<string>> DownloadResume(int language, Guid trialId, Guid[] doctorIdArray)
 | ||
|         {
 | ||
|             var zipPath = await _fileService.CreateOfficialResumeZip(language, doctorIdArray);
 | ||
| 
 | ||
|             return ResponseOutput.Ok(zipPath);
 | ||
|         }
 | ||
|     }
 | ||
|     #endregion
 | ||
| 
 | ||
| 
 | ||
|     #region 项目 系统  基本文件 上传  下载 预览
 | ||
| 
 | ||
|     [ApiExplorerSettings(GroupName = "Common")]
 | ||
|     [ApiController]
 | ||
|     public class UploadDownLoadController : UploadBaseController
 | ||
|     {
 | ||
|         public IMapper _mapper { get; set; }
 | ||
|         public IUserInfo _userInfo { get; set; }
 | ||
|         private readonly IMediator _mediator;
 | ||
| 
 | ||
|         private readonly IWebHostEnvironment _hostEnvironment;
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         public UploadDownLoadController(IMapper mapper, IUserInfo userInfo, IMediator mediator, IWebHostEnvironment hostEnvironment)
 | ||
|         {
 | ||
|             _hostEnvironment = hostEnvironment;
 | ||
|             _mediator = mediator;
 | ||
|             _mapper = mapper;
 | ||
|             _userInfo = userInfo;
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>  缩略图 </summary>
 | ||
|         [AllowAnonymous]
 | ||
|         [HttpGet("Common/LocalFilePreview")]
 | ||
|         public async Task<FileContentResult> LocalFilePreview(string relativePath)
 | ||
|         {
 | ||
| 
 | ||
|             var _fileStorePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, relativePath);
 | ||
| 
 | ||
|             var storePreviewPath = _fileStorePath + ".preview.jpeg";
 | ||
| 
 | ||
|             if (!System.IO.File.Exists(storePreviewPath))
 | ||
|             {
 | ||
|                 ImageHelper.ResizeSave(_fileStorePath, storePreviewPath);
 | ||
|             }
 | ||
| 
 | ||
|             return new FileContentResult(await System.IO.File.ReadAllBytesAsync(storePreviewPath), "image/jpeg");
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         /// <summary>  通用文件下载 </summary>
 | ||
|         [AllowAnonymous]
 | ||
|         [HttpGet("CommonDocument/DownloadCommonDoc")]
 | ||
|         public async Task<IActionResult> DownloadCommonFile(string code, [FromServices] IRepository<CommonDocument> _commonDocumentRepository)
 | ||
|         {
 | ||
|             var (filePath, fileName) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code);
 | ||
| 
 | ||
|             new FileExtensionContentTypeProvider().Mappings.TryGetValue(Path.GetExtension(filePath), out var contentType);
 | ||
| 
 | ||
|             return File(System.IO.File.OpenRead(filePath), contentType ?? "application/octet-stream", fileName);
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 下载项目临床数据文件
 | ||
|         /// </summary>
 | ||
|         /// <param name="clinicalDataTrialSetId"></param>
 | ||
|         /// <param name="_clinicalDataTrialSetRepository"></param>
 | ||
|         /// <returns></returns>
 | ||
|         [AllowAnonymous]
 | ||
|         [HttpGet("CommonDocument/DownloadTrialClinicalFile")]
 | ||
|         public async Task<IActionResult> DownloadTrialClinicalFile(Guid clinicalDataTrialSetId, [FromServices] IRepository<ClinicalDataTrialSet> _clinicalDataTrialSetRepository)
 | ||
|         {
 | ||
|             var (filePath, fileName) = await FileStoreHelper.GetTrialClinicalPathAsync(_hostEnvironment, _clinicalDataTrialSetRepository, clinicalDataTrialSetId);
 | ||
| 
 | ||
|             new FileExtensionContentTypeProvider().Mappings.TryGetValue(Path.GetExtension(filePath), out var contentType);
 | ||
| 
 | ||
|             return File(System.IO.File.OpenRead(filePath), contentType ?? "application/octet-stream", fileName);
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 下载系统临床数据文件
 | ||
|         /// </summary>
 | ||
|         /// <param name="clinicalDataSystemSetId"></param>
 | ||
|         /// <param name="_clinicalDataSystemSetRepository"></param>
 | ||
|         /// <returns></returns>
 | ||
|         [AllowAnonymous]
 | ||
|         [HttpGet("CommonDocument/DownloadSystemClinicalFile")]
 | ||
|         public async Task<IActionResult> DownloadSystemClinicalFile(Guid clinicalDataSystemSetId, [FromServices] IRepository<ClinicalDataSystemSet> _clinicalDataSystemSetRepository)
 | ||
|         {
 | ||
|             var (filePath, fileName) = await FileStoreHelper.GetSystemClinicalPathAsync(_hostEnvironment, _clinicalDataSystemSetRepository, clinicalDataSystemSetId);
 | ||
| 
 | ||
|             new FileExtensionContentTypeProvider().Mappings.TryGetValue(Path.GetExtension(filePath), out var contentType);
 | ||
| 
 | ||
|             return File(System.IO.File.OpenRead(filePath), contentType ?? "application/octet-stream", fileName);
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         ///上传项目签名文档
 | ||
|         /// </summary>
 | ||
|         /// <param name="trialId"></param>
 | ||
|         /// <returns></returns>
 | ||
|         [HttpPost("TrialDocument/UploadTrialDoc/{trialId:guid}")]
 | ||
|         [DisableRequestSizeLimit]
 | ||
|         [DisableFormValueModelBinding]
 | ||
|         public async Task<IResponseOutput> UploadTrialDoc(Guid trialId)
 | ||
|         {
 | ||
| 
 | ||
|             return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetTrialSignDocPath(_hostEnvironment, trialId, fileName));
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 上传系统签名文档
 | ||
|         /// </summary>
 | ||
|         /// <returns></returns>
 | ||
|         [HttpPost("TrialDocument/UploadSystemDoc")]
 | ||
|         [DisableRequestSizeLimit]
 | ||
|         [DisableFormValueModelBinding]
 | ||
|         public async Task<IResponseOutput> UploadSysTemDoc()
 | ||
|         {
 | ||
| 
 | ||
|             return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetSystemSignDocPath(_hostEnvironment, fileName));
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 上传通用文档  比如一致性核查的 比如导出的excel 模板
 | ||
|         /// </summary>
 | ||
|         /// <returns></returns>
 | ||
|         [HttpPost("CommonDocument/UploadCommonDoc")]
 | ||
|         [DisableRequestSizeLimit]
 | ||
|         [DisableFormValueModelBinding]
 | ||
|         public async Task<IResponseOutput> UploadCommonDoc()
 | ||
|         {
 | ||
| 
 | ||
|             return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetCommonDocPath(_hostEnvironment, fileName));
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 上传系统通知文档
 | ||
|         /// </summary>
 | ||
|         /// <returns></returns>
 | ||
|         [HttpPost("SystemNotice/UploadSystemNoticeDoc")]
 | ||
|         [DisableRequestSizeLimit]
 | ||
|         [DisableFormValueModelBinding]
 | ||
|         public async Task<IResponseOutput> UploadSystemNoticeDoc()
 | ||
|         {
 | ||
| 
 | ||
|             return await SingleFileUploadAsync((fileName) => FileStoreHelper.GetSystemNoticePath(_hostEnvironment, fileName));
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
|     }
 | ||
|     #endregion
 | ||
| 
 | ||
| }
 |