using AutoMapper; using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Infrastructure.Extention; using MediatR; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.WebUtilities; using Microsoft.Net.Http.Headers; using System; using System.IO; using System.Linq; using System.Threading.Tasks; namespace IRaCIS.Core.API.Controllers { [ApiExplorerSettings(GroupName = "Trial")] [ApiController] public class UploadController : ControllerBase { public IMapper _mapper { get; set; } public IUserInfo _userInfo { get; set; } private readonly IMediator _mediator; private readonly IWebHostEnvironment _hostEnvironment; private readonly IServiceProvider _serviceProvider; public UploadController(IMapper mapper, IUserInfo userInfo, IMediator mediator, IWebHostEnvironment hostEnvironment, IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; _hostEnvironment = hostEnvironment; _mediator = mediator; _mapper = mapper; _userInfo = userInfo; } [HttpPost("TrialDocument/UploadTrialDoc/{trialId:guid}/{type}")] [DisableRequestSizeLimit] [DisableFormValueModelBinding] public async Task UploadTrialDoc(Guid trialId,string type) { 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) { DealTrialStorePath(trialId, type, contentDisposition.FileName.Value, out string serverFilePath, out string relativePath ); await WriteFileAsync(section.Body, serverFilePath); //仅仅返回一个文件,如果多文件上传 在最后返回多个路径 return ResponseOutput.Ok(new { FilePath = relativePath, FullFilePath = relativePath + "?access_token=" + _userInfo.UserToken }); } section = await reader.ReadNextSectionAsync(); } return ResponseOutput.Ok(); } [HttpPost("TrialDocument/UploadSystemDoc/{type}")] [DisableRequestSizeLimit] [DisableFormValueModelBinding] public async Task UploadSysTemDoc( string type) { 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) { DealSysTemStorePath( type, contentDisposition.FileName.Value, out string serverFilePath, out string relativePath); await WriteFileAsync(section.Body, serverFilePath); //仅仅返回一个文件,如果多文件上传 在最后返回多个路径 return ResponseOutput.Ok(new { FilePath = relativePath, FullFilePath = relativePath + "?access_token=" + _userInfo.UserToken }); } section = await reader.ReadNextSectionAsync(); } return ResponseOutput.Ok(); } /// /// 上传通用文档 比如一致性核查的 比如导出的excel 模板 /// /// [HttpPost("CommonDocument/UploadCommonDoc/{fileType}/{moduleType}")] [DisableRequestSizeLimit] [DisableFormValueModelBinding] public async Task UploadCommonDoc(string fileType, string moduleType) { 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) { DealCommonStorePath(fileType, moduleType, contentDisposition.FileName.Value, out string serverFilePath, out string relativePath); await WriteFileAsync(section.Body, serverFilePath); //仅仅返回一个文件,如果多文件上传 在最后返回多个路径 return ResponseOutput.Ok(new { FilePath = relativePath, FullFilePath = relativePath + "?access_token=" + _userInfo.UserToken }); } section = await reader.ReadNextSectionAsync(); } return ResponseOutput.Ok(); } private void DealCommonStorePath(string fileType, string moduleType, string fileRealName, out string serverFilePath, out string relativePath) { var rootPath = Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\')).FullName; //上传根路径 var _fileStorePath = Path.Combine(rootPath, StaticData.CommonFileFolder); //文件类型路径处理 var uploadFolderPath = Path.Combine(_fileStorePath, moduleType, fileType); if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); var fileNameEX = Path.GetExtension(fileRealName); var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileNameEX; relativePath = $"/{StaticData.CommonFileFolder}/{moduleType}/{fileType}/{trustedFileNameForFileStorage}"; serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); } private void DealSysTemStorePath( string type, string fileRealName, out string serverFilePath, out string relativePath) { var rootPath = Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\')).FullName; //上传根路径 var _fileStorePath = Path.Combine(rootPath, StaticData.TrialDataFolder); //文件类型路径处理 var uploadFolderPath = Path.Combine(_fileStorePath, "SysTemDocument", type); if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); var fileNameEX = Path.GetExtension(fileRealName); var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileNameEX; relativePath = $"/{StaticData.TrialDataFolder}/SysTemDocument/{type}/{trustedFileNameForFileStorage}"; serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); } private void DealTrialStorePath(Guid trialId,string type,string fileRealName, out string serverFilePath, out string relativePath) { var rootPath = Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\')).FullName; //上传根路径 var _fileStorePath = Path.Combine(rootPath, StaticData.TrialDataFolder); //文件类型路径处理 var uploadFolderPath = Path.Combine(_fileStorePath, trialId.ToString(), type); if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); var fileNameEX = Path.GetExtension(fileRealName); var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileNameEX; relativePath = $"/{StaticData.TrialDataFolder}/{trialId}/{type}/{trustedFileNameForFileStorage}"; serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); } /// /// 上传临床数据 /// /// /// 1:DICOM DTF 2:非DIOM DTF 3: 受试者临床数据 /// /// [HttpPost("ClinicalData/UploadVisitClinicalData/{trialId:guid}/{subjectVisitId:guid}/{type}")] [DisableRequestSizeLimit] [DisableFormValueModelBinding] [Obsolete] public async Task UploadVisitData(Guid subjectVisitId, [FromRoute] UploadFileTypeEnum uploadType, [FromServices] IRepository _subjectVisitRepository) { 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) { DealStorePath(subjectVisitId, contentDisposition.FileName.Value, uploadType, out string serverFilePath, out string relativePath, _subjectVisitRepository); await WriteFileAsync(section.Body, serverFilePath); //仅仅返回一个文件,如果多文件上传 在最后返回多个路径 return ResponseOutput.Ok(new { FilePath = relativePath, FullFilePath = relativePath + "?access_token=" + _userInfo.UserToken }); } section = await reader.ReadNextSectionAsync(); } return ResponseOutput.Ok(); } public enum UploadFileTypeEnum { DICOM_DTF = 1, NonDICOM_DTF = 2, SubjectTreatement = 3 } private void DealStorePath(Guid subjectVisitId, string realName, UploadFileTypeEnum typeEnum, out string serverFilePath, out string relativePath, IRepository _subjectVisitRepository) { var rootPath = Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\')).FullName; //上传根路径 var _fileStorePath = Path.Combine(rootPath, StaticData.TrialDataFolder); var sv = _subjectVisitRepository.Where(t => t.Id == subjectVisitId).Select(t => new { t.TrialId, t.SiteId, t.SubjectId }).FirstOrDefault(); //处理存储的文件夹 var typeFolder = typeEnum == UploadFileTypeEnum.SubjectTreatement ? StaticData.TreatmenthistoryFolder : typeEnum == UploadFileTypeEnum.NonDICOM_DTF ? StaticData.NoneDicomFolder : /*typeEnum == UploadFileTypeEnum.DICOM_DTF ?*/ StaticData.DicomFolder; string uploadFolderPath = Path.Combine(_fileStorePath, sv.TrialId.ToString(), sv.SiteId.ToString(), sv.SubjectId.ToString(), subjectVisitId.ToString(), typeFolder); if (!Directory.Exists(uploadFolderPath)) { Directory.CreateDirectory(uploadFolderPath); } var fileNameEX = Path.GetExtension(realName); var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileNameEX; relativePath = $"/{StaticData.TrialDataFolder}/{sv.TrialId}/{sv.SiteId}/{sv.SubjectId}/{subjectVisitId}/{typeFolder}/{trustedFileNameForFileStorage}"; serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); //处理 是上传文件返回路径 还是上传文件后,需要保存数据库 if (typeEnum == UploadFileTypeEnum.SubjectTreatement) { var repository = _serviceProvider.GetService(typeof(IRepository)) as IRepository; _= repository.InsertOrUpdateAsync(new PreviousPDFAddOrEdit() { FileName = realName, Path = relativePath, SubjectVisitId = subjectVisitId }, true).Result; } else if (typeEnum == UploadFileTypeEnum.NonDICOM_DTF) { } else if (typeEnum == UploadFileTypeEnum.NonDICOM_DTF) { } } /// /// 写文件导到磁盘 /// /// 流 /// 文件保存路径 /// private static async Task WriteFileAsync(System.IO.Stream stream, string path) { const int FILE_WRITE_SIZE = 84975;//写出缓冲区大小 int writeCount = 0; using (FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write, FILE_WRITE_SIZE, true)) { byte[] byteArr = new byte[FILE_WRITE_SIZE]; int readCount = 0; while ((readCount = await stream.ReadAsync(byteArr, 0, byteArr.Length)) > 0) { await fileStream.WriteAsync(byteArr, 0, readCount); writeCount += readCount; } } return writeCount; } } }