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

404 lines
16 KiB
C#

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<IResponseOutput> 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<IResponseOutput> 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();
}
/// <summary>
/// 上传通用文档 比如一致性核查的 比如导出的excel 模板
/// </summary>
/// <returns></returns>
[HttpPost("CommonDocument/UploadCommonDoc/{fileType}/{moduleType}")]
[DisableRequestSizeLimit]
[DisableFormValueModelBinding]
public async Task<IResponseOutput> 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();
}
/// <summary>
/// 上传系统通知文档
/// </summary>
/// <returns></returns>
[HttpPost("SystemNotice/UploadSystemNoticeDoc")]
[DisableRequestSizeLimit]
[DisableFormValueModelBinding]
public async Task<IResponseOutput> UploadSystemNoticeDoc()
{
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)
{
DealSystemNoticePath( 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 DealSystemNoticePath(string fileRealName, out string serverFilePath, out string relativePath)
{
var rootPath = Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\')).FullName;
//上传根路径
var _fileStorePath = Path.Combine(rootPath, StaticData.SystemNoticeFolder);
//文件类型路径处理
var uploadFolderPath = Path.Combine(_fileStorePath);
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
var fileNameEX = Path.GetExtension(fileRealName);
var trustedFileNameForFileStorage = fileRealName+Guid.NewGuid().ToString() + fileNameEX;
relativePath = $"/{StaticData.CommonFileFolder}/{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);
}
/// <summary>
/// 上传临床数据
/// </summary>
/// <param name="subjectVisitId"></param>
/// <param name="uploadType"> 1:DICOM DTF 2:非DIOM DTF 3: 受试者临床数据</param>
/// <param name="_subjectVisitRepository"></param>
/// <returns></returns>
[HttpPost("ClinicalData/UploadVisitClinicalData/{trialId:guid}/{subjectVisitId:guid}/{type}")]
[DisableRequestSizeLimit]
[DisableFormValueModelBinding]
[Obsolete]
public async Task<IResponseOutput> UploadVisitData(Guid subjectVisitId, [FromRoute] UploadFileTypeEnum uploadType, [FromServices] IRepository<SubjectVisit> _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<SubjectVisit> _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<PreviousPDF>)) as IRepository<PreviousPDF>;
_= repository.InsertOrUpdateAsync(new PreviousPDFAddOrEdit() { FileName = realName, Path = relativePath, SubjectVisitId = subjectVisitId }, true).Result;
}
else if (typeEnum == UploadFileTypeEnum.NonDICOM_DTF)
{
}
else if (typeEnum == UploadFileTypeEnum.NonDICOM_DTF)
{
}
}
/// <summary>
/// 写文件导到磁盘
/// </summary>
/// <param name="stream">流</param>
/// <param name="path">文件保存路径</param>
/// <returns></returns>
private static async Task<int> 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;
}
}
}