1258 lines
49 KiB
C#
1258 lines
49 KiB
C#
using AutoMapper;
|
||
using DocumentFormat.OpenXml.Drawing;
|
||
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.ImageAndDoc;
|
||
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 SharpCompress.Common;
|
||
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;
|
||
using Path = System.IO.Path;
|
||
|
||
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;
|
||
private readonly QCCommon _qCCommon;
|
||
public StudyController(IMapper mapper, IUserInfo userInfo, IWebHostEnvironment hostEnvironment, IMediator mediator, IEasyCachingProvider provider,
|
||
QCCommon qCCommon,
|
||
IRepository repository)
|
||
{
|
||
_qCCommon = qCCommon;
|
||
_provider = provider;
|
||
_hostEnvironment = hostEnvironment;
|
||
_mediator = mediator;
|
||
|
||
_mapper = mapper;
|
||
_userInfo = userInfo;
|
||
_repository = repository;
|
||
}
|
||
|
||
[HttpPost, Route("Study/PreArchiveStudy")]
|
||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||
public async Task<IResponseOutput> PreArchiveStudy(PreArchiveStudyCommand preArchiveStudyCommand,
|
||
[FromServices] IStudyService _studyService,
|
||
[FromServices] IRepository<StudyMonitor> _studyMonitorRepository)
|
||
{
|
||
|
||
if (_provider.Get<List<SystemAnonymization>>(StaticData.Anonymize.Anonymize_AddFixedFiled).Value == null)
|
||
{
|
||
await _mediator.Send(new AnonymizeCacheRequest());
|
||
}
|
||
|
||
var savedInfo = _studyService.GetSaveToDicomInfo(preArchiveStudyCommand.SubjectVisitId);
|
||
|
||
var studyMonitor = new StudyMonitor()
|
||
{
|
||
TrialId = savedInfo.TrialId,
|
||
SiteId = savedInfo.SiteId,
|
||
SubjectId = savedInfo.SubjectId,
|
||
SubjectVisitId = savedInfo.SubjectVisitId,
|
||
|
||
IsSuccess = false,
|
||
UploadStartTime = DateTime.Now,
|
||
IsDicom = preArchiveStudyCommand.IsDicom,
|
||
IP = _userInfo.IP
|
||
};
|
||
|
||
|
||
var addEntity = await _studyMonitorRepository.AddAsync(studyMonitor, true);
|
||
|
||
return ResponseOutput.Ok(addEntity.Id);
|
||
|
||
}
|
||
|
||
|
||
/// <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, Guid studyMonitorId,
|
||
[FromServices] ILogger<UploadDownLoadController> _logger,
|
||
[FromServices] IEasyCachingProvider _provider,
|
||
[FromServices] IStudyService _studyService,
|
||
[FromServices] IHubContext<UploadHub, IUploadClient> _uploadHub,
|
||
[FromServices] IDicomArchiveService _dicomArchiveService,
|
||
[FromServices] IRepository<StudyMonitor> _studyMonitorRepository
|
||
)
|
||
{
|
||
|
||
|
||
|
||
|
||
|
||
|
||
if (!HttpContext.Request.HasFormContentType ||
|
||
!MediaTypeHeaderValue.TryParse(HttpContext.Request.ContentType, out var mediaTypeHeader) ||
|
||
string.IsNullOrEmpty(mediaTypeHeader.Boundary.Value))
|
||
{
|
||
//---不支持的MediaType
|
||
return ResponseOutput.NotOk(StaticData.International("UploadDownLoad_UnsupportedMedia"));
|
||
}
|
||
|
||
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}") && _provider.Get<Guid>($"StudyUid_{trialId}_{studyInstanceUid}").Value == _userInfo.Id)
|
||
{
|
||
_provider.Set($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}", _userInfo.Id, TimeSpan.FromMinutes(30));
|
||
}
|
||
|
||
|
||
|
||
//if (_provider.Exists($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}"))
|
||
//{
|
||
// //---当前已有人正在上传和归档该检查!
|
||
// return ResponseOutput.NotOk(StaticData.International("UploadDownLoad_ArchiveInProgress"));
|
||
//}
|
||
//else
|
||
//{
|
||
// _provider.Set($"StudyUid_{trialId}_{archiveStudyCommand.StudyInstanceUid}", _userInfo.Id, TimeSpan.FromMinutes(30));
|
||
//}
|
||
|
||
//到了接口,代表上传结束了
|
||
|
||
var studyMonitor = await _studyMonitorRepository.FirstOrDefaultAsync(t => t.Id == studyMonitorId);
|
||
|
||
studyMonitor.UploadFinishedTime = DateTime.Now;
|
||
|
||
|
||
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(StaticData.International("UploadDownLoad_RequestError"));
|
||
}
|
||
|
||
studyMonitor.FileSize = (decimal)HttpContext.Request.ContentLength;
|
||
studyMonitor.FileCount = archiveResult.ReceivedFileCount;
|
||
studyMonitor.FailedFileCount = archiveResult.ErrorFiles.Count;
|
||
studyMonitor.IsDicomReUpload = archiveStudyCommand.AbandonStudyId != null;
|
||
studyMonitor.Note = JsonConvert.SerializeObject(archiveResult);
|
||
|
||
|
||
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;
|
||
|
||
}
|
||
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
|
||
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.ArchiveFinishedTime = DateTime.Now;
|
||
|
||
await _studyMonitorRepository.SaveChangesAsync();
|
||
}
|
||
|
||
|
||
|
||
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)]
|
||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||
|
||
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]
|
||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt", "AfterStopCannNotOpt" })]
|
||
|
||
|
||
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]
|
||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||
|
||
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>
|
||
/// 上传截图
|
||
/// </summary>
|
||
/// <param name="subjectId"></param>
|
||
/// <returns></returns>
|
||
[HttpPost("Printscreen/UploadPrintscreen/{subjectId:guid}")]
|
||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||
public async Task<IResponseOutput<FileDto>> UploadPrintscreen(Guid subjectId)
|
||
{
|
||
|
||
var subjectInfo = await this._repository.Where<Subject>(x => x.Id == subjectId).FirstNotNullAsync();
|
||
|
||
FileDto fileDto = new FileDto();
|
||
await FileUploadAsync(async (fileName) =>
|
||
{
|
||
var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetUploadPrintscreenFilePath(_hostEnvironment, fileName, subjectInfo.TrialId, subjectInfo.SiteId, subjectInfo.Id);
|
||
fileDto.Path = relativePath;
|
||
fileDto.FileName = fileName;
|
||
await Task.CompletedTask;
|
||
return serverFilePath;
|
||
});
|
||
|
||
|
||
return ResponseOutput.Ok(fileDto);
|
||
}
|
||
|
||
|
||
/// <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);
|
||
}
|
||
|
||
|
||
|
||
public class UploadNoneDicomFileCommand
|
||
{
|
||
public Guid TrialId { get; set; }
|
||
public Guid SubjectVisitId { get; set; }
|
||
public Guid NoneDicomStudyId { get; set; }
|
||
public Guid StudyMonitorId { get; set; }
|
||
|
||
|
||
public List<OSSFileDTO> UploadedFileList { get; set; } = new List<OSSFileDTO>();
|
||
|
||
|
||
public class OSSFileDTO
|
||
{
|
||
public string FilePath { get; set; }
|
||
public string FileName { get; set; }
|
||
public int FileFize { get; set; }
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 上传非Dicom 文件 支持压缩包 多文件上传
|
||
/// </summary>
|
||
/// <param name="_noneDicomStudyRepository"></param>
|
||
/// <returns></returns>
|
||
//[DisableRequestSizeLimit]
|
||
[HttpPost("NoneDicomStudy/UploadNoneDicomFile")]
|
||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||
//[Authorize(Policy = IRaCISPolicy.CRC)]
|
||
public async Task<IResponseOutput> UploadNoneDicomFile(UploadNoneDicomFileCommand incommand,
|
||
[FromServices] IRepository<NoneDicomStudy> _noneDicomStudyRepository, [FromServices] IRepository<StudyMonitor> _studyMonitorRepository)
|
||
{
|
||
|
||
var subjectVisitId = incommand.SubjectVisitId;
|
||
var studyMonitorId = incommand.StudyMonitorId;
|
||
var noneDicomStudyId = incommand.NoneDicomStudyId;
|
||
|
||
|
||
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();
|
||
|
||
var studyMonitor = await _studyMonitorRepository.FirstOrDefaultAsync(t => t.Id == studyMonitorId);
|
||
|
||
studyMonitor.UploadFinishedTime = DateTime.Now;
|
||
|
||
foreach (var item in incommand.UploadedFileList)
|
||
{
|
||
await _repository.AddAsync(new NoneDicomStudyFile() { FileName = item.FileName, Path = item.FilePath, NoneDicomStudyId = noneDicomStudyId });
|
||
|
||
}
|
||
var uploadFinishedTime = DateTime.Now;
|
||
|
||
var noneDicomStudy = await _noneDicomStudyRepository.FirstOrDefaultAsync((t => t.Id == noneDicomStudyId));
|
||
|
||
noneDicomStudy.FileCount = noneDicomStudy.FileCount + incommand.UploadedFileList.Count;
|
||
|
||
studyMonitor.FileCount = incommand.UploadedFileList.Count;
|
||
studyMonitor.FileSize = incommand.UploadedFileList.Sum(t => t.FileFize);
|
||
studyMonitor.IsDicom = false;
|
||
studyMonitor.IsDicomReUpload = false;
|
||
studyMonitor.StudyId = noneDicomStudyId;
|
||
studyMonitor.StudyCode = noneDicomStudy.StudyCode;
|
||
studyMonitor.ArchiveFinishedTime = DateTime.Now;
|
||
studyMonitor.IP = _userInfo.IP;
|
||
|
||
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"))
|
||
{
|
||
//---支持.xlsx、.xls、.csv格式的文件上传。
|
||
throw new BusinessValidationFailedException(StaticData.International("UploadDownLoad_SupportedFormats"));
|
||
}
|
||
|
||
(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(StaticData.International("UploadDownLoad_InvalidData"));
|
||
}
|
||
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(StaticData.International("UploadDownLoad_InvalidData"));
|
||
}
|
||
|
||
}
|
||
|
||
|
||
await _mediator.Send(new ConsistencyVerificationRequest() { ETCList = etcCheckList, TrialId = trialId });
|
||
|
||
return ResponseOutput.Ok();
|
||
|
||
}
|
||
|
||
|
||
[HttpPost]
|
||
[UnitOfWork]
|
||
public async Task<IResponseOutput> UploadTrialSiteSurveyUser(Guid trialId,
|
||
[FromServices] IRepository<TrialSite> _trialSiteRepository,
|
||
[FromServices] IRepository<UserType> _usertypeRepository,
|
||
[FromServices] ITrialSiteSurveyService _trialSiteSurveyService)
|
||
{
|
||
var (serverFilePath, relativePath, fileName) = (string.Empty, string.Empty, string.Empty);
|
||
await FileUploadAsync(async (realFileName) =>
|
||
{
|
||
fileName = realFileName;
|
||
|
||
if (!fileName.EndsWith(".xlsx", StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
throw new BusinessValidationFailedException("请用提供格式的模板excel上传需要处理的数据");
|
||
}
|
||
|
||
(serverFilePath, relativePath) = FileStoreHelper.GetTrialSiteSurveyFilePath(_hostEnvironment, fileName, trialId);
|
||
|
||
return serverFilePath;
|
||
});
|
||
|
||
//去掉空白行
|
||
var excelList = MiniExcel.Query<SiteSurveyUserImportDto>(serverFilePath).ToList()
|
||
.Where(t => !(string.IsNullOrWhiteSpace(t.TrialSiteCode) && string.IsNullOrWhiteSpace(t.FirstName) && string.IsNullOrWhiteSpace(t.LastName)) && string.IsNullOrWhiteSpace(t.Email)
|
||
&& string.IsNullOrWhiteSpace(t.Phone) && string.IsNullOrWhiteSpace(t.UserTypeStr) && string.IsNullOrWhiteSpace(t.OrganizationName));
|
||
|
||
if (excelList.Any(t => string.IsNullOrWhiteSpace(t.TrialSiteCode) || string.IsNullOrWhiteSpace(t.FirstName) || string.IsNullOrWhiteSpace(t.LastName) || string.IsNullOrWhiteSpace(t.Email) || string.IsNullOrWhiteSpace(t.UserTypeStr)))
|
||
{
|
||
throw new BusinessValidationFailedException("请确保Excel中 每一行的 中心编号,姓名,邮箱,用户类型数据记录完整再进行上传");
|
||
}
|
||
|
||
var siteCodeList = excelList.Select(t => t.TrialSiteCode.Trim()).Distinct().ToList();
|
||
|
||
if (_trialSiteRepository.Where(t => siteCodeList.Contains(t.TrialSiteCode)).Count() != siteCodeList.Count)
|
||
{
|
||
throw new BusinessValidationFailedException("在项目中未找到该Excel中部分或全部中心");
|
||
}
|
||
|
||
if (excelList.GroupBy(t => new { t.UserTypeStr, t.Email }).Any(g => g.Count() > 1))
|
||
{
|
||
throw new BusinessValidationFailedException("同一邮箱,同一用户类型,只能生成一个账户,请核查Excel数据");
|
||
}
|
||
|
||
if (excelList.Any(t => t.Email.Contains("@")))
|
||
{
|
||
throw new BusinessValidationFailedException("有邮箱不符合邮箱格式,请核查Excel数据");
|
||
}
|
||
var generateUserTypeList = new List<string>() { "CRC", "SR", "CRA" };
|
||
|
||
if (excelList.Any(t => !generateUserTypeList.Contains(t.UserTypeStr.ToUpper())))
|
||
{
|
||
throw new BusinessValidationFailedException("用户类型仅能为 CRC,SR,CRA 请核查Excel数据");
|
||
}
|
||
|
||
//处理好 用户类型 和用户类型枚举
|
||
var sysUserTypeList = _usertypeRepository.Where(t => t.UserTypeEnum == UserTypeEnum.CRA || t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator || t.UserTypeEnum == UserTypeEnum.SR).Select(t => new { UserTypeId = t.Id, t.UserTypeEnum }).ToList();
|
||
var siteList= _trialSiteRepository.Where(t=>t.TrialId==trialId && siteCodeList.Contains(t.TrialSiteCode)).Select(t=>new {t.TrialSiteCode,t.SiteId}).ToList();
|
||
|
||
foreach (var item in excelList)
|
||
{
|
||
switch (item.UserTypeStr.ToUpper())
|
||
{
|
||
case "CRC":
|
||
|
||
item.UserTypeId = sysUserTypeList.FirstOrDefault(t => t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).UserTypeId;
|
||
item.UserTypeEnum = UserTypeEnum.ClinicalResearchCoordinator;
|
||
break;
|
||
|
||
case "CRA":
|
||
item.UserTypeId = sysUserTypeList.FirstOrDefault(t => t.UserTypeEnum == UserTypeEnum.CRA).UserTypeId;
|
||
item.UserTypeEnum = UserTypeEnum.CRA;
|
||
break;
|
||
|
||
case "SR":
|
||
item.UserTypeId = sysUserTypeList.FirstOrDefault(t => t.UserTypeEnum == UserTypeEnum.SR).UserTypeId;
|
||
item.UserTypeEnum = UserTypeEnum.SR;
|
||
break;
|
||
|
||
}
|
||
|
||
item.SiteId = siteList.FirstOrDefault(t => t.TrialSiteCode.ToUpper() == item.TrialSiteCode.ToUpper()).SiteId;
|
||
}
|
||
|
||
await _trialSiteSurveyService.ImportGenerateAccountAndJoinTrialAsync(trialId, excelList.ToList());
|
||
|
||
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));
|
||
}
|
||
|
||
|
||
|
||
|
||
}
|
||
#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
|
||
|
||
}
|