irc-netcore-api/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs

1040 lines
39 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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.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.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.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<int> DicomFileUploadAsync(Func<string, Stream, Task> filePathFunc)
{
var fileCount = 0;
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 ?? 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());
}
}
}
//普通单个文件
else
{
if (mediaType.Contains("octet-stream"))
{
++fileCount;
await filePathFunc(fileName, section.Body);
}
}
}
section = await reader.ReadNextSectionAsync();
}
return fileCount;
}
}
#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;
public StudyController(IMapper mapper, IUserInfo userInfo, IWebHostEnvironment hostEnvironment, IMediator mediator,
IRepository repository)
{
_hostEnvironment = hostEnvironment;
_mediator = mediator;
_mapper = mapper;
_userInfo = userInfo;
_repository = repository;
}
/// <summary>Dicom 归档</summary>
[HttpPost, Route("Study/ArchiveStudy/{trialId:guid}")]
[DisableFormValueModelBinding]
[DisableRequestSizeLimit]
[TypeFilter(typeof(TrialResourceFilter))]
public async Task<IResponseOutput> ArchiveStudyNew([FromForm] ArchiveStudyCommand archiveStudyCommand,
[FromServices] ILogger<UploadDownLoadController> _logger,
[FromServices] IEasyCachingProvider _provider,
[FromServices] IStudyService _studyService,
[FromServices] IDicomArchiveService _dicomArchiveService,
[FromServices] IRepository _repository
)
{
string studycode = string.Empty;
var startTime = DateTime.Now;
if (_provider.Exists("StudyUid_" + archiveStudyCommand.StudyInstanceUid))
{
return ResponseOutput.NotOk("当前已有人正在上传和归档该检查!");
}
else
{
_provider.Set("StudyUid_" + 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);
archiveResult.ReceivedFileCount = await DicomFileUploadAsync(async (fileName, fileStream) =>
{
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 });
}
}
}
catch (Exception e)
{
_logger.LogError(e.Message + e.StackTrace);
archiveResult.ErrorFiles.Add(fileName);
_provider.Remove("StudyUid_" + archiveStudyCommand.StudyInstanceUid);
}
});
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;
await _repository.AddAsync(new StudyMonitor()
{
TrialId = savedInfo.TrialId,
SiteId = savedInfo.SiteId,
SubjectId = savedInfo.SubjectId,
SubjectVisitId = savedInfo.SubjectVisitId,
StudyId = archivedStudyIds[0],
StudyCode = studycode,
UploadStartTime = startTime,
UploadFinishedTime = DateTime.Now,
FileSize = (decimal)HttpContext.Request.ContentLength,
FileCount = archiveResult.ReceivedFileCount,
IsDicom = true,
IsDicomReUpload = archiveStudyCommand.AbandonStudyId != null,
IP = _userInfo.IP
}, true);
//_studyService.UploadOrReUploadNeedTodo(archiveStudyCommand, archivedStudyIds, ref archiveResult, );
_provider.Remove("StudyUid_" + archiveStudyCommand.StudyInstanceUid);
}
else
{
return ResponseOutput.NotOk(archiveResult);
}
}
catch (Exception e)
{
_logger.LogError(e.Message + e.StackTrace);
_provider.Remove("StudyUid_" + archiveStudyCommand.StudyInstanceUid);
return ResponseOutput.NotOk(e.Message, ApiResponseCodeEnum.ProgramException);
}
return ResponseOutput.Ok(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
});
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
});
return serverFilePath;
});
return ResponseOutput.Ok(fileDtos);
}
/// <summary>
/// 上传医学审核图片
/// </summary>
/// <param name="trialId"></param>
/// <param name="taskMedicalReviewId"></param>
/// <returns></returns>
[HttpPost("TaskMedicalReview/UploadMedicalReviewImage/{trialId:guid}/{taskMedicalReviewId:guid}")]
[TypeFilter(typeof(TrialResourceFilter))]
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))]
[Authorize(Policy = IRaCISPolicy.CRC)]
public async Task<IResponseOutput> UploadNoneDicomFile(IFormCollection formCollection, Guid subjectVisitId, Guid noneDicomStudyId)
{
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 studyCode = await _repository.Where<NoneDicomStudy>(t => t.Id == noneDicomStudyId).Select(t => t.StudyCode).FirstOrDefaultAsync();
await _repository.AddAsync(new StudyMonitor()
{
FileCount = formCollection.Files.Count,
FileSize = formCollection.Files.Sum(t => t.Length),
IsDicom = false,
IsDicomReUpload = false,
StudyId = noneDicomStudyId,
StudyCode = 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))]
[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 = _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))]
[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
}