优化上传代码

This commit is contained in:
hang
2022-05-29 17:46:14 +08:00
parent ae70c7f69b
commit 5d96df5d00
26 changed files with 1567 additions and 2361 deletions
@@ -1,94 +0,0 @@
using AutoMapper;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure.Extention;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Threading.Tasks;
namespace IRaCIS.Core.API.Controllers
{
[ApiExplorerSettings(GroupName = "Trial")]
[ApiController]
public class CommonController : ControllerBase
{
public IMapper _mapper { get; set; }
public IUserInfo _userInfo { get; set; }
private readonly IWebHostEnvironment _hostEnvironment;
public CommonController(IMapper mapper, IUserInfo userInfo, IMediator mediator, IWebHostEnvironment hostEnvironment)
{
_hostEnvironment = hostEnvironment;
_mapper = mapper;
_userInfo = userInfo;
}
[AllowAnonymous]
[HttpGet("Common/LocalFilePreview")]
public async Task<FileContentResult> LocalFilePreview(string relativePath)
{
var rootPath = Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\')).IfNullThrowException().FullName;
var _fileStorePath = Path.Combine(rootPath, relativePath.Replace('/', '\\').Trim('\\'));
var storePreviewPath = _fileStorePath + ".preview.jpeg";
//if (!System.IO.File.Exists(storePreviewPath))
//{
ImageResizeHelper.ResizeSave(_fileStorePath, storePreviewPath);
//}
return new FileContentResult(await System.IO.File.ReadAllBytesAsync(storePreviewPath), "image/jpeg");
//_logger.LogError(rootPath);
//_logger.LogError(_fileStorePath);
//if (!File.Exists(storePreviewPath))
//{
//Bitmap sourceImage = new Bitmap(File.OpenRead(_fileStorePath));
//System.Drawing.Image destinationImage = new Bitmap(500, 500);
//Graphics g = Graphics.FromImage(destinationImage);
//g.DrawImage(
// sourceImage,
// new Rectangle(0, 0, 500, 500),
// new Rectangle(0, 0, sourceImage.Width, sourceImage.Height),
// GraphicsUnit.Pixel
//);
//destinationImage.Save(storePreviewPath);
//var image = SKBitmap.Decode(_fileStorePath);
////设置图片新的size
//var newImg = image.Resize(new SKSizeI(50, 50), SKFilterQuality.Medium);
//using var fs = new FileStream(storePreviewPath, FileMode.Create);
//newImg.Encode(fs, SKEncodedImageFormat.Png, 100);
//fs.Flush();
//var image = NetVips.Image.NewFromFile(_fileStorePath);
//var newImg = image.Resize(0.5);
//newImg.WriteToFile(storePreviewPath);
//var image = NetVips.Image.NewFromFile(_fileStorePath);
//var newImg = image.ThumbnailImage(500);
//newImg.WriteToFile(_fileStorePath);
}
}
}
@@ -1,95 +0,0 @@
using AutoMapper;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Infra.EFCore;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using IRaCIS.Core.Domain.Share;
using Microsoft.EntityFrameworkCore;
using IRaCIS.Core.Application.Helper;
namespace IRaCIS.Core.API.Controllers
{
[ApiExplorerSettings(GroupName = "Trial")]
[ApiController]
public class DownLoadController : ControllerBase
{
public IMapper _mapper { get; set; }
public IUserInfo _userInfo { get; set; }
private readonly IWebHostEnvironment _hostEnvironment;
public DownLoadController(IMapper mapper, IUserInfo userInfo, IMediator mediator, IWebHostEnvironment hostEnvironment)
{
_hostEnvironment = hostEnvironment;
_mapper = mapper;
_userInfo = userInfo;
}
//[HttpGet("VisitPlan/DownloadInflunceStudyList{trialId:guid}/{createTime:dateTime}")]
//public async Task<IActionResult> DownloadInflunceStudyList(Guid trialId, DateTime createTime, [FromServices] IRepository<VisitPlanInfluenceSubjectVisit> _influnceRepository)
//{
// var list = _influnceRepository.Where(t => t.TrialId == trialId && t.CreateTime == createTime)
// .ProjectTo<VisitPlanInfluenceSubjectVisitDTO>(_mapper.ConfigurationProvider).ToList();
// if (list.Count == 0)
// {
// list.Add(new VisitPlanInfluenceSubjectVisitDTO() { CreateTime = DateTime.Now, SubjectCode = "test", StudyTime = DateTime.Now, IsDicomStudy = false, HistoryWindow = "test" });
// }
// IExporter exporter = new ExcelExporter();
// var result = await exporter.ExportAsByteArray(list);
// return new XlsxFileResult(bytes: bytes);
// //return File(result, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"检查导出_{DateTime.Now}.xlsx");
//}
[AllowAnonymous]
[HttpGet("CommonDocument/DownloadCommonDoc")]
public async Task<IActionResult> DownloadCommonFile(string code, [FromServices] IRepository<CommonDocument> _commonDocumentRepository)
{
var doc = await _commonDocumentRepository.AsQueryable(true).FirstOrDefaultAsync(t => t.Code == code);
if (doc == null)
{
throw new Exception("当前code 没要找到对应的文件");
}
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
var filePath = Path.Combine(rootPath, doc.Path.Trim('/'));
if (!System.IO.File.Exists(filePath))
{
throw new Exception("服务器本地不存在该路径文件");
}
new FileExtensionContentTypeProvider().Mappings.TryGetValue(Path.GetExtension(filePath), out var contentType);
return File(System.IO.File.OpenRead(filePath), contentType ?? "application/octet-stream", doc.Name);
}
}
}
@@ -79,18 +79,6 @@ namespace IRaCIS.Api.Controllers
[HttpPost, Route("enroll/downloadResume/{trialId:guid}/{language}")]
[TypeFilter(typeof(TrialResourceFilter))]
[AllowAnonymous]
public async Task<IResponseOutput<string>> DownloadResume([FromServices] IFileService _fileService, int language, Guid trialId, Guid[] doctorIdArray)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
var zipPath = await _fileService.CreateOfficialResumeZip(language, doctorIdArray);
return ResponseOutput.Ok(zipPath);
}
/// <summary> 系统用户登录接口[New] </summary>
@@ -1,532 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.API.Utility;
using IRaCIS.Core.Application.Contracts.Image;
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Contracts;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 文件上传
/// </summary>
[Route("file")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Common")]
public class FileController : ControllerBase
{
private readonly IFileService _fileService;
private readonly IWebHostEnvironment _webHostEnvironment;
private readonly IHostEnvironment _hostEnvironment;
private ILogger<FileController> _logger;
private string _targetFilePath;
private readonly long _fileSizeLimit;
private readonly string[] _permittedExtensions = { ".pdf", ".doc", ".docx" };
public string trustedFileNameForFileStorage = "";
// Get the default form options so that we can use them to set the default
// limits for request body data.
private static readonly FormOptions _defaultFormOptions = new FormOptions();
private string defaultUploadFilePath = string.Empty;
public FileController(IFileService fileService, Microsoft.Extensions.Configuration.IConfiguration config,
IHostEnvironment hostEnvironment, ILogger<FileController> logger,
IWebHostEnvironment webHostEnvironment)
{
_fileService = fileService;
_hostEnvironment = hostEnvironment;
_webHostEnvironment = webHostEnvironment;
_fileSizeLimit = config.GetValue<long>("FileSizeLimit");
defaultUploadFilePath = Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\')).FullName;
_logger = logger;
_logger.LogWarning("File Path:" + defaultUploadFilePath);
}
/// <summary>
/// 上传文件[FileUpload]
/// </summary>
/// <param name="attachmentType">附件类型</param>
/// <param name="doctorId">医生Id</param>
/// <returns>返回文件信息</returns>
[HttpPost, Route("uploadFile/{attachmentType}/{doctorId}")]
[DisableFormValueModelBinding]
public async Task<IActionResult> UploadOrdinaryFile(string attachmentType, Guid doctorId)
{
#region
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
{
ModelState.AddModelError("File",
$"The request couldn't be processed (Error 1).");
// Log error
return BadRequest(ModelState);
}
var boundary = MultipartRequestHelper.GetBoundary(
MediaTypeHeaderValue.Parse(Request.ContentType),
_defaultFormOptions.MultipartBoundaryLengthLimit);
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)
{
// This check assumes that there's a file
// present without form data. If form data
// is present, this method immediately fails
// and returns the model error.
if (!MultipartRequestHelper
.HasFileContentDisposition(contentDisposition))
{
ModelState.AddModelError("File",
$"The request couldn't be processed (Error 2).");
// Log error
return BadRequest(ModelState);
}
else
{
// Don't trust the file name sent by the client. To display
// the file name, HTML-encode the value.
var trustedFileNameForDisplay = WebUtility.HtmlEncode(
contentDisposition.FileName.Value);
//var trustedFileNameForFileStorage = Path.GetRandomFileName();
trustedFileNameForFileStorage = contentDisposition.FileName.Value;
// **WARNING!**
// In the following example, the file is saved without
// scanning the file's contents. In most production
// scenarios, an anti-virus/anti-malware scanner API
// is used on the file before making the file available
// for download or for use by other systems.
// For more information, see the topic that accompanies
// this sample.
var streamedFileContent = await FileHelpers.ProcessStreamedFile(
section, contentDisposition, ModelState,
_permittedExtensions, _fileSizeLimit);
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
//实际文件处理
string uploadFolderPath = Path.Combine(defaultUploadFilePath, "UploadFile/" + doctorId + "/");
var doctorAttachmentUploadFolder = Path.Combine(uploadFolderPath, attachmentType);
_targetFilePath = doctorAttachmentUploadFolder;
if (!Directory.Exists(doctorAttachmentUploadFolder)) Directory.CreateDirectory(doctorAttachmentUploadFolder);
using (var targetStream = System.IO.File.Create(
Path.Combine(_targetFilePath, trustedFileNameForFileStorage)))
{
await targetStream.WriteAsync(streamedFileContent);
var attachmentPath = $"/UploadFile/{doctorId}/{attachmentType}/{trustedFileNameForFileStorage}";
return new JsonResult(ResponseOutput.Ok(new UploadFileInfoDTO() { FilePath = attachmentPath, FullFilePath = attachmentPath + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7) }));
}
}
}
// Drain any remaining section body that hasn't been consumed and
// read the headers for the next section.
section = await reader.ReadNextSectionAsync();
}
return Created(nameof(FileController), null);
#endregion
}
/// <summary>
/// 上传文件( 不是医生个人的文件)[FileUpload]
/// 例如:阅片章程等
/// </summary>
/// <param name="type">文件类型</param>
/// <returns></returns>
[HttpPost, Route("uploadNonDoctorFile/{type}")]
[DisableFormValueModelBinding]
public async Task<IActionResult> UploadNonDoctorFile(string type)
{
#region New Test OK
//上传根路径
string uploadFolderPath = Path.Combine(defaultUploadFilePath, "UploadFile");
if (uploadFolderPath != null)
{
//文件类型路径处理
var uploadTypePath = Path.Combine(uploadFolderPath, type);
if (!Directory.Exists(uploadTypePath)) Directory.CreateDirectory(uploadTypePath);
////实际文件处理
_targetFilePath = uploadTypePath;
//获取boundary
#region
var boundary = MultipartRequestHelper.GetBoundary(
MediaTypeHeaderValue.Parse(Request.ContentType),
_defaultFormOptions.MultipartBoundaryLengthLimit);
#endregion
#region
//var boundary = HeaderUtilities.RemoveQuotes(MediaTypeHeaderValue.Parse(Request.ContentType).Boundary).Value;
#endregion
//得到reader
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
//{ BodyLengthLimit = 2000 };//
var section = await reader.ReadNextSectionAsync();
//读取section
while (section != null)
{
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
if (hasContentDispositionHeader)
{
trustedFileNameForFileStorage = contentDisposition.FileName.Value;
await WriteFileAsync(section.Body, Path.Combine(_targetFilePath, trustedFileNameForFileStorage));
#region
//using (var targetStream = System.IO.File.Create(
// Path.Combine(_targetFilePath, trustedFileNameForFileStorage)))
//{
// using (var memoryStream = new MemoryStream())
// {
// await section.Body.CopyToAsync(memoryStream);
// await targetStream.WriteAsync(memoryStream.ToArray());
// }
//}
#endregion
var attachmentPath = $"/UploadFile/{type}/{trustedFileNameForFileStorage}";
return new JsonResult(ResponseOutput.Ok(new UploadFileInfoDTO() { FilePath = attachmentPath, FullFilePath = attachmentPath + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7) }));
}
section = await reader.ReadNextSectionAsync();
}
return Created(nameof(FileController), null);
}
return new JsonResult(ResponseOutput.NotOk("服务器端映射路径操作失败"));
#endregion
}
/// <summary>
/// 写文件导到磁盘
/// </summary>
/// <param name="stream">流</param>
/// <param name="path">文件保存路径</param>
/// <returns></returns>
public 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;
}
#region
/// <summary>
/// 下载多个医生的所有附件
/// </summary>
/// <param name="doctorIds"></param>
/// <returns></returns>
[HttpPost, Route("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("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("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)
});
}
#endregion
#region
public class UploadDTFCommand
{
public Guid TrialId { get; set; }
public Guid SiteId { get; set; }
public Guid SubjectId { get; set; }
public Guid SubjectVisitId { get; set; }
}
/// <summary>
/// 流式上传 临时文件
/// </summary>
/// <returns></returns>
[HttpPost("UploadDTF/{trialId:guid}/{siteId:guid}/{subjectId:guid}/{subjectVisitId:guid}/{studyId:guid}")]
[DisableFormValueModelBinding]
[DisableRequestSizeLimit]
[Obsolete]
public async Task<IResponseOutput> UploadingStream(Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId, Guid studyId, [FromServices] IStudyDTFService studyDTFService)
{
//上传根路径
string uploadFolderPath = Path.Combine(defaultUploadFilePath, "Dicom");
var dtfPath = Path.Combine(uploadFolderPath, DateTime.Now.Year.ToString(), trialId.ToString(),
siteId.ToString(), subjectId.ToString(), subjectVisitId.ToString());
if (!Directory.Exists(dtfPath))
{
Directory.CreateDirectory(dtfPath);
}
#region DTF
////上传根路径
//string uploadFolderPath = Path.Combine(defaultUploadFilePath, "UploadFile");
////文件类型路径处理
//var uploadTempFilePath = Path.Combine(uploadFolderPath, "TempFile");
//if (!Directory.Exists(uploadTempFilePath)) Directory.CreateDirectory(uploadTempFilePath);
//var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileNameEX;
//await WriteFileAsync(section.Body, Path.Combine(uploadTempFilePath, trustedFileNameForFileStorage));
//var attachmentPath = $"{uploadTempFilePath}/{trustedFileNameForFileStorage}";
////多个文件上传,在这里返回就不合适,需要在外层,返回所有的文件路径,实际需要时再更改
//return ResponseOutput.Ok(new UploadFileInfoDTO() { FilePath = attachmentPath });
#endregion
//获取boundary
var boundary = HeaderUtilities.RemoveQuotes(MediaTypeHeaderValue.Parse(Request.ContentType).Boundary).Value;
//得到reader
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
var section = await reader.ReadNextSectionAsync();
//读取section
while (section != null)
{
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
if (hasContentDispositionHeader)
{
var realName = contentDisposition.FileName.Value;
var fileNameEX = Path.GetExtension(contentDisposition.FileName.Value);
var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileNameEX;
var relativePath = $"/Dicom/{DateTime.Now.Year.ToString()}/{trialId}/{siteId}/{subjectId}/{subjectVisitId}/{trustedFileNameForFileStorage}";
studyDTFService.AddStudyDTF(new Core.Application.Contracts.Dicom.DTO.StudyDTFAddOrUpdateCommand()
{
StudyId = studyId,
FileName = realName,
Path = relativePath
});
await WriteFileAsync(section.Body, Path.Combine(dtfPath, trustedFileNameForFileStorage));
//仅仅返回一个文件,如果多文件上传 在最后返回多个路径
return ResponseOutput.Ok(new UploadFileInfoDTO() { FilePath = relativePath, FullFilePath = relativePath + "?access_token=" + HttpContext.Request.Headers["Authorization"].ToString().Substring(7) });
}
section = await reader.ReadNextSectionAsync();
}
return ResponseOutput.NotOk("Upload error");
}
/// <summary>
/// 流式上传 非Dicom文件
/// </summary>
/// <returns></returns>
[HttpPost("UploadNoneDICOM")]
[DisableFormValueModelBinding]
[DisableRequestSizeLimit]
[Obsolete]
public async Task<IResponseOutput> UploadingNoneDicomStream([FromForm] ArchiveStudyCommand archiveStudyCommand, [FromServices] IStudyService studyService)
{
//上传根路径
string uploadFolderPath = Path.Combine(defaultUploadFilePath, "Dicom");
//文件类型路径处理
//var noneDicomPath = Path.Combine(uploadFolderPath, DateTime.Now.Year.ToString(), archiveStudyCommand.TrialId.ToString(),
// archiveStudyCommand.SiteId.ToString(), archiveStudyCommand.SubjectId.ToString(), archiveStudyCommand.SubjectVisitId.ToString(), "Data");
//var dtfPath = Path.Combine(uploadFolderPath, DateTime.Now.Year.ToString(), archiveStudyCommand.TrialId.ToString(),
// archiveStudyCommand.SiteId.ToString(), archiveStudyCommand.SubjectId.ToString(), archiveStudyCommand.SubjectVisitId.ToString());
var noneDicomPath = string.Empty;
var dtfPath = string.Empty;
var tempDtfPath = Path.Combine(defaultUploadFilePath/*, archiveStudyCommand.DTFPath*/);
if (!Directory.Exists(noneDicomPath))
{
Directory.CreateDirectory(noneDicomPath);
}
if (!System.IO.File.Exists(tempDtfPath))
{
return ResponseOutput.NotOk("DTF file can not found");
}
System.IO.File.Move(tempDtfPath, dtfPath);
var saveFileDic = new Dictionary<string, string>();
//获取boundary
var boundary = HeaderUtilities.RemoveQuotes(MediaTypeHeaderValue.Parse(Request.ContentType).Boundary).Value;
//得到reader
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
var section = await reader.ReadNextSectionAsync();
//读取section
while (section != null)
{
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
if (hasContentDispositionHeader)
{
var fileName = contentDisposition.FileName.Value;
var fileNameEX = Path.GetExtension(contentDisposition.FileName.Value);
var trustedFileNameForFileStorage = Guid.NewGuid() + fileNameEX;
await WriteFileAsync(section.Body, Path.Combine(noneDicomPath, trustedFileNameForFileStorage));
var attachmentPath = $"{noneDicomPath}/{trustedFileNameForFileStorage}";
saveFileDic.Add(attachmentPath, fileName);
}
section = await reader.ReadNextSectionAsync();
}
//处理数据库操作
//studyService.DealNonDicomFile(saveFileDic, archiveStudyCommand);
return ResponseOutput.Ok(saveFileDic);
}
#endregion
}
}
@@ -10,7 +10,6 @@ using System.Threading.Tasks;
using IRaCIS.Application.Services;
using IRaCIS.Core.Application.Service.Inspection.DTO;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Application.Service.Inspection.Interface;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Application.Auth;
@@ -23,15 +22,12 @@ namespace IRaCIS.Core.API.Controllers.Special
{
private readonly ITrialService _trialService;
private readonly ICalculateService _calculateService;
private readonly IInspectionService _inspectionService;
public FinancialChangeController(ITrialService trialService, ICalculateService calculateService,
IInspectionService inspectionService
public FinancialChangeController(ITrialService trialService, ICalculateService calculateService
)
{
_trialService = trialService;
_calculateService = calculateService;
this._inspectionService = inspectionService;
}
@@ -1,14 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using Castle.Core.Internal;
using IRaCIS.Application.Contracts;
using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Image.QA;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.Service.Inspection.DTO;
@@ -1,432 +0,0 @@
using IRaCIS.Application.Interfaces;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using Microsoft.Net.Http.Headers;
using Microsoft.AspNetCore.WebUtilities;
using System.Threading.Tasks;
using IRaCIS.Core.Application.Contracts.Dicom;
using System.IO;
using System.IO.Compression;
using Microsoft.Extensions.Logging;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Infrastructure.Extention;
using EasyCaching.Core;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Application.Service.Inspection.Interface;
using IRaCIS.Core.Domain.Share;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// Study
/// </summary>
[Route("study")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Image")]
public class StudyController : ControllerBase
{
private readonly IStudyService _studyService;
private readonly IDicomArchiveService _dicomArchiveService;
private readonly ILogger<StudyController> _logger;
private readonly IDictionaryService _dictionaryService;
private readonly IInspectionService _inspectionService;
private IEasyCachingProvider _provider;
private IUserInfo _userInfo;
private static object _locker = new object();
public StudyController(IStudyService studyService,
IDicomArchiveService dicomArchiveService,
ILogger<StudyController> logger,
IDictionaryService dictionaryService,
IInspectionService inspectionService,
IEasyCachingProvider provider, IUserInfo userInfo
)
{
_userInfo = userInfo;
_provider = provider;
_studyService = studyService;
_dicomArchiveService = dicomArchiveService;
_logger = logger;
this._dictionaryService = dictionaryService;
this._inspectionService = inspectionService;
}
/// <summary> 归档</summary>
[HttpPost, Route("archiveStudy/{trialId:guid}")]
[DisableFormValueModelBinding]
[DisableRequestSizeLimit]
[TypeFilter(typeof(TrialResourceFilter))]
public async Task<IResponseOutput> ArchiveStudy([FromForm] ArchiveStudyCommand archiveStudyCommand)
{
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 = new DicomArchiveResult();
var archivedStudyIds = new List<Guid>();
var seriesInstanceUidList = new List<string>();
var instanceUidList = new List<string>();
//重传的时候,找出当前检查已经上传的series instance
if (archiveStudyCommand.AbandonStudyId != null)
{
_studyService.GetHasUploadSeriesAndInstance(archiveStudyCommand.AbandonStudyId.Value, ref seriesInstanceUidList, ref instanceUidList);
}
var savedInfo = _studyService.GetSaveToDicomInfo(archiveStudyCommand.SubjectVisitId);
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)
{
//采用post方式 这里多加一个判断 过滤其他参数
if (string.IsNullOrEmpty(section.ContentType))
{
section = await reader.ReadNextSectionAsync();
continue;
}
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
if (hasContentDispositionHeader)
{
string fileName = contentDisposition.FileName.Value;
try
{
string mediaType = section.ContentType;
if (mediaType.Contains("zip"))
{
var partStream = section.Body;
using (var zipArchive = new ZipArchive(partStream, ZipArchiveMode.Read))
{
foreach (var entry in zipArchive.Entries)
{
if (entry.FullName.EndsWith("/")) continue;
try
{
++archiveResult.ReceivedFileCount;
using (var memoryStream = new MemoryStream())
{
await section.Body.CopyToAsync(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
var archiveStudyId = await _dicomArchiveService.ArchiveDicomStreamAsync(memoryStream, savedInfo, seriesInstanceUidList, instanceUidList);
studycode = archiveStudyId.Item2;
if (!archivedStudyIds.Contains(archiveStudyId.Item1))
archivedStudyIds.Add(archiveStudyId.Item1);
}
}
catch
{
archiveResult.ErrorFiles.Add($"{fileName}/{entry.FullName}");
}
}
}
}
++archiveResult.ReceivedFileCount;
if (mediaType.Contains("octet-stream"))
{
using (var memoryStream = new MemoryStream())
{
await section.Body.CopyToAsync(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
var archiveStudyId = await _dicomArchiveService.ArchiveDicomStreamAsync(memoryStream, savedInfo, seriesInstanceUidList, instanceUidList);
studycode = archiveStudyId.Item2;
if (!archivedStudyIds.Contains(archiveStudyId.Item1))
archivedStudyIds.Add(archiveStudyId.Item1);
}
}
}
catch (Exception e)
{
_logger.LogError(e.Message + e.StackTrace);
archiveResult.ErrorFiles.Add(fileName);
_provider.Remove("StudyUid_" + archiveStudyCommand.StudyInstanceUid);
}
}
section = await reader.ReadNextSectionAsync();
}
try
{
if (archivedStudyIds.Count > 0) // 上传成功,处理逻辑
{
// 同一个访视 多个线程上传处理 批量保存 可能造成死锁 https://www.cnblogs.com/johnblogs/p/9945767.html
await _dicomArchiveService.DicomDBDataSaveChange();
//sw.Stop();
_studyService.UploadOrReUploadNeedTodo(archiveStudyCommand, archivedStudyIds, ref archiveResult, new StudyMonitor()
{
TrialId = savedInfo.TrialId,
SiteId = savedInfo.SiteId,
SubjectId = savedInfo.SubjectId,
SubjectVisitId = savedInfo.SubjectVisitId,
StudyId = archivedStudyIds[0],
StudyCode= studycode,
UploadStartTime = startTime,
UploadFinishedTime = DateTime.Now,
//TotalMillisecondsInterval = (DateTime.Now- startTime).TotalMilliseconds,
FileSize = (decimal)HttpContext.Request.ContentLength,
FileCount = archiveResult.ReceivedFileCount,
IsDicom = true,
IsDicomReUpload = archiveStudyCommand.AbandonStudyId != null,
IP = _userInfo.IP
});
_provider.Remove("StudyUid_" + archiveStudyCommand.StudyInstanceUid);
}
else
{
return ResponseOutput.NotOk("未完成该检查的归档");
}
}
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);
}
#region 2021.12.14
//[Obsolete]
//[HttpGet, Route("forwardStudy/{studyId:guid}/{trialId:guid}")]
//[TrialAudit(AuditType.StudyAudit, AuditOptType.Forwarded)]
//[TypeFilter(typeof(TrialResourceFilter))]
//public IResponseOutput ForwardStudy(Guid studyId)
//{
// return _studyService.ForwardStudy(studyId);
//}
///// <summary> 指定资源Id,获取Dicom检查信息 </summary>
///// <param name="studyId"> Dicom检查的Id </param>
//[HttpGet, Route("item/{studyId:guid}")]
//[Obsolete]
//public IResponseOutput<DicomStudyDTO> GetStudyItem(Guid studyId)
//{
// return ResponseOutput.Ok(_studyService.GetStudyItem(studyId));
//}
//[Obsolete]
//[HttpDelete, Route("deleteStudy/{id:guid}/{trialId:guid}")]
//public IResponseOutput DeleteStudy(Guid id)
//{
// return _studyService.DeleteStudy(id);
//}
//[Obsolete]
//[HttpPost, Route("getStudyList")]
//public IResponseOutput<PageOutput<StudyDTO>> GetStudyList(StudyQueryDTO queryDto)
//{
// return ResponseOutput.Ok(_studyService.GetStudyList(queryDto));
//}
/////// <summary> 指定资源Id,渲染Dicom检查的Jpeg预览图像 </summary>
/////// <param name="studyId"> Dicom检查的Id </param>
////[HttpGet, Route("preview/{studyId:guid}")]
////[AllowAnonymous]
////public FileContentResult GetStudyPreview(Guid studyId)
////{
//// string path = _studyService.GetStudyPreview(studyId);
//// using (var sw = DicomRenderingHelper.RenderPreviewJpeg(path))
//// {
//// var bytes = new byte[sw.Length];
//// sw.Read(bytes, 0, bytes.Length);
//// sw.Close();
//// return new FileContentResult(bytes, "image/jpeg");
//// }
////}
///// <summary>
///// Dicom匿名化
///// </summary>
///// <param name="studyId">需要匿名化的检查Id</param>
///// <returns></returns>
//[HttpPost, Route("dicomAnonymize/{studyId:guid}/{trialId:guid}")]
//[TrialAudit(AuditType.StudyAudit, AuditOptType.Anonymized)]
//[Obsolete]
//[TypeFilter(typeof(TrialResourceFilter))]
//public async Task<IResponseOutput> DicomAnonymize(Guid studyId)
//{
// string userName = User.FindFirst("realName").Value; ;
// return await _studyService.DicomAnonymize(studyId, userName);
//}
///// <summary>
///// 获取受试者 这次访视 对应的study modality 列表
///// </summary>
///// <param name="trialId"></param>
///// <param name="siteId"></param>
///// <param name="subjectId"></param>
///// <param name="subjectVisitId"></param>
///// <returns></returns>
//[HttpPost, Route("getSubjectVisitStudyList/{trialId:guid}/{siteId:guid}/{subjectId:guid}/{subjectVisitId:guid}")]
//[Obsolete]
//[AllowAnonymous]
//public IResponseOutput<List<SubjectVisitStudyDTO>> GetSubjectVisitStudyList(Guid trialId, Guid siteId, Guid subjectId,
// Guid subjectVisitId)
//{
// return ResponseOutput.Ok(_studyService.GetSubjectVisitStudyList(trialId, siteId, subjectId, subjectVisitId));
//}
//[HttpPost, Route("getDistributeStudyList")]
//[Obsolete]
//public IResponseOutput<PageOutput<DistributeReviewerStudyStatusDTO>> GetDistributeStudyList(StudyStatusQueryDTO studyStatusQueryDto)
//{
// return ResponseOutput.Ok(_studyService.GetDistributeStudyList(studyStatusQueryDto));
//}
/////// <summary> 删除检查</summary>
////[HttpDelete, Route("deleteStudy/{id:guid}/{trialId:guid}")]
////
////[TypeFilter(typeof(TrialResourceFilter))]
////public IResponseOutput DeleteStudy(Guid id)
////{
//// return _studyService.DeleteStudy(id);
////}
///// <summary> 更新Study状态,并保存状态变更信息 </summary>
///// <param name="studyStatusDetailCommand"></param>
//[HttpPost, Route("updateStudyStatus/{trialId:guid}")]
//[TrialAudit(AuditType.StudyAudit, AuditOptType.ChangeStudyStatus)]
//[Obsolete]
//[TypeFilter(typeof(TrialResourceFilter))]
//public IResponseOutput UpdateStudyStatus(StudyStatusDetailCommand studyStatusDetailCommand)
//{
// return _studyService.UpdateStudyStatus(studyStatusDetailCommand);
//}
///// <summary>
///// 根据项目Id 获取可选医生列表
///// </summary>
///// <param name="trialId"></param>
///// <returns></returns>
//[HttpGet, Route("GetReviewerList/{trialId:guid}")]
//[Obsolete]
//public IResponseOutput<List<ReviewerDistributionDTO>> GetReviewerListByTrialId(Guid trialId)
//{
// var result = _studyService.GetReviewerListByTrialId(trialId);
// return ResponseOutput.Ok(result);
//}
///// <summary>
///// 根据StudyId获取该Study的操作记录,时间倒序
///// </summary>
///// <param name="studyId"></param>
///// <returns></returns>
//[HttpGet, Route("getStudyStatusDetailList/{studyId:guid}")]
//[Obsolete]
//public IResponseOutput<List<StudyStatusDetailDTO>> GetStudyStatusDetailList(Guid studyId)
//{
// var result = _studyService.GetStudyStatusDetailList(studyId);
// return ResponseOutput.Ok(result);
//}
///// <summary>
///// 获取某个访视的关联访视
///// 用于获取关联影像(调用之前的接口:/series/list/,根据StudyId,获取访视的序列列表)
///// </summary>
///// <param name="visitNum"></param>
///// <param name="tpCode"></param>
///// <returns></returns>
//[HttpGet, Route("getRelationVisitList/{visitNum}/{tpCode}")]
//[Obsolete]
//[AllowAnonymous]
//public IResponseOutput<IEnumerable<RelationVisitDTO>> GetRelationVisitList(decimal visitNum, string tpCode)
//{
// return ResponseOutput.Ok(_studyService.GetRelationVisitList(visitNum, tpCode));
//}
///// <summary>
///// 保存标记(跟删除合并,每次保存最新的标记),会删除替换之前的标记
///// 外层的TPcode 必须传,里面的标记数组可为空数组,表示删除该Study的所有标记
///// </summary>
///// <param name="imageLabelCommand"></param>
///// <returns></returns>
//[HttpPost, Route("saveImageLabelList")]
//[AllowAnonymous]
//[Obsolete]
//public IResponseOutput SaveImageLabelList(ImageLabelCommand imageLabelCommand)
//{
// return ResponseOutput.Result(_studyService.SaveImageLabelList(imageLabelCommand));
//}
///// <summary>
///// 根据TPCode 获取所有的标记
///// </summary>
///// <param name="tpCode"></param>
///// <returns></returns>
//[HttpGet, Route("getImageLabelList/{tpCode}")]
//[Obsolete]
//[AllowAnonymous]
//public IResponseOutput<IEnumerable<ImageLabelDTO>> GetImageLabelList(string tpCode)
//{
// return ResponseOutput.Ok(_studyService.GetImageLabel(tpCode));
//}
#endregion
}
}
@@ -1,405 +0,0 @@
using AutoMapper;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Helper;
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}")]
[DisableRequestSizeLimit]
[DisableFormValueModelBinding]
public async Task<IResponseOutput> UploadTrialDoc(Guid trialId)
{
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, 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")]
[DisableRequestSizeLimit]
[DisableFormValueModelBinding]
public async Task<IResponseOutput> UploadSysTemDoc( )
{
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( 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")]
[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 = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment) ;
//上传根路径
var _fileStorePath = Path.Combine(rootPath, StaticData.SystemDataFolder);
//文件类型路径处理
var uploadFolderPath = Path.Combine(_fileStorePath, StaticData.DataTemplate);
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
var (trustedFileNameForFileStorage, fileName) = FileStoreHelper.GetStoreFileName(fileRealName);
relativePath = $"/{StaticData.IRaCISDataFolder}/{StaticData.SystemDataFolder}/{StaticData.DataTemplate}/{trustedFileNameForFileStorage}";
serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
}
private void DealSystemNoticePath(string fileRealName, out string serverFilePath, out string relativePath)
{
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
//上传根路径
var _fileStorePath = Path.Combine(rootPath, StaticData.SystemDataFolder);
//文件类型路径处理
var uploadFolderPath = Path.Combine(_fileStorePath, StaticData.NoticeAttachment);
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
var (trustedFileNameForFileStorage, fileName) = FileStoreHelper.GetStoreFileName(fileRealName);
relativePath = $"/{StaticData.IRaCISDataFolder}/{StaticData.SystemDataFolder}/{StaticData.NoticeAttachment}/{trustedFileNameForFileStorage}";
serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
}
private void DealSysTemStorePath( string fileRealName, out string serverFilePath, out string relativePath)
{
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
//上传根路径
var _fileStorePath = Path.Combine(rootPath, StaticData.SystemDataFolder);
//文件类型路径处理
var uploadFolderPath = Path.Combine(_fileStorePath, StaticData.SignDocumentFolder);
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
//var fileNameEX = Path.GetExtension(fileRealName);
//var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileNameEX;
var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileRealName;
relativePath = $"/{StaticData.IRaCISDataFolder}/{StaticData.SystemDataFolder}/{ StaticData.SignDocumentFolder}/{trustedFileNameForFileStorage}";
serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
}
private void DealTrialStorePath(Guid trialId,string fileRealName, out string serverFilePath, out string relativePath)
{
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
//上传根路径
var _fileStorePath = Path.Combine(rootPath, StaticData.TrialDataFolder);
//文件类型路径处理
var uploadFolderPath = Path.Combine(_fileStorePath, trialId.ToString(), StaticData.SignDocumentFolder);
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
var (trustedFileNameForFileStorage, fileName) = FileStoreHelper.GetStoreFileName(fileRealName);
relativePath = $"/{StaticData.IRaCISDataFolder}/{StaticData.TrialDataFolder}/{trialId}/{StaticData.SignDocumentFolder}/{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 = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
//上传根路径
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;
}
}
}
File diff suppressed because it is too large Load Diff