优化上传代码

This commit is contained in:
2022-05-29 17:46:14 +08:00
parent ae70c7f69b
commit 5d96df5d00
26 changed files with 1567 additions and 2361 deletions
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Hosting;
using IRaCIS.Core.Application.Helper;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using MiniExcelLibs;
@@ -9,24 +10,12 @@ public static class ExcelExportHelper
//MiniExcel_Export
public static async Task<IActionResult> DataExportAsync(string code, object data, string exportFileNamePrefix, IRepository<CommonDocument> _commonDocumentRepository, IWebHostEnvironment _hostEnvironment)
{
var doc = _commonDocumentRepository.AsQueryable(true).FirstOrDefault(t => t.Code == code);
if (doc == null)
{
throw new Exception("程序没有找到对应的数据模板文件,请联系系统运维人员。");
}
var (physicalPath, fileNmae) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code);
var rootPath = Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\'))?.FullName;
var filePath = Path.Combine(rootPath, doc.Path.Trim('/'));
if (!System.IO.File.Exists(filePath))
{
throw new Exception("数据模板文件存储路径上未找对应文件,请联系系统运维人员。");
}
//模板路径
var tplPath = filePath;
var tplPath = physicalPath;
#region MiniExcel
@@ -38,7 +27,7 @@ public static class ExcelExportHelper
return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
{
FileDownloadName = $"{exportFileNamePrefix}_{doc.Name.Substring(0,doc.Name.LastIndexOf('.'))}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
FileDownloadName = $"{exportFileNamePrefix}_{fileNmae.Substring(0, fileNmae.LastIndexOf('.'))}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
};
#endregion
@@ -1,6 +1,7 @@
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using Microsoft.AspNetCore.Hosting;
namespace IRaCIS.Core.Application.Helper;
@@ -9,7 +10,7 @@ public static class FileStoreHelper
{
//处理文件名 压缩包,或者目录类的 会带上相对路径
public static (string TrustedFileNameForFileStorage, string RealName) GetStoreFileName(string fileName)
{
@@ -29,17 +30,273 @@ public static class FileStoreHelper
return (trustedFileNameForFileStorage, fileName);
}
public static string GetIRaCISRootDataFolder(IWebHostEnvironment _hostEnvironment)
//API vue 部署目录
public static string GetIRaCISRootPath(IWebHostEnvironment _hostEnvironment)
{
var root = (Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\'))).IfNullThrowException().FullName;
var rootPath = (Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\'))).IfNullThrowException().FullName;
return rootPath;
}
var rootFolder =Path.Combine(root, StaticData.IRaCISDataFolder) ;
//获取环境存储根目录
public static string GetIRaCISRootDataFolder(IWebHostEnvironment _hostEnvironment)
{
var rootPath = GetIRaCISRootPath(_hostEnvironment);
var rootFolder = Path.Combine(rootPath, StaticData.IRaCISDataFolder);
return rootFolder;
}
//根据相对路径 获取具体文件物理地址
public static string GetPhysicalFilePath(IWebHostEnvironment _hostEnvironment, string relativePath)
{
var rootPath = GetIRaCISRootPath(_hostEnvironment);
var physicalFilePath = Path.Combine(rootPath, relativePath.Trim('/'));
return physicalFilePath;
}
//通过编码获取通用文档具体物理路径
public static async Task<(string PhysicalPath, string FileName)> GetCommonDocPhysicalFilePathAsync(IWebHostEnvironment _hostEnvironment, IRepository<CommonDocument> _commonDocumentRepository, string code)
{
var doc = await _commonDocumentRepository.FirstOrDefaultAsync(t => t.Code == code);
if (doc == null)
{
throw new BusinessValidationFailedException("数据库没有找到对应的数据模板文件,请联系系统运维人员。");
}
var filePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, doc.Path);
if (!System.IO.File.Exists(filePath))
{
throw new BusinessValidationFailedException("数据模板文件存储路径上未找对应文件,请联系系统运维人员。");
}
return (filePath, doc.Name.Trim('/'));
}
/// <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;
}
// 获取项目签名文档存放路径
public static (string PhysicalPath, string RelativePath) GetTrialSignDocPath(IWebHostEnvironment _hostEnvironment, Guid trialId, string fileName)
{
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
//文件类型路径处理
var uploadFolderPath = Path.Combine(rootPath, StaticData.TrialDataFolder, trialId.ToString(), StaticData.SignDocumentFolder);
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
var relativePath = $"/{StaticData.IRaCISDataFolder}/{StaticData.TrialDataFolder}/{trialId}/{StaticData.SignDocumentFolder}/{trustedFileNameForFileStorage}";
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
return (serverFilePath, relativePath);
}
// 获取系统签名文档存放路径
public static (string PhysicalPath, string RelativePath) GetSystemSignDocPath(IWebHostEnvironment _hostEnvironment, string fileName)
{
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
//文件类型路径处理
var uploadFolderPath = Path.Combine(rootPath, StaticData.SystemDataFolder, StaticData.SignDocumentFolder);
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
var relativePath = $"/{StaticData.IRaCISDataFolder}/{StaticData.SystemDataFolder}/{ StaticData.SignDocumentFolder}/{trustedFileNameForFileStorage}";
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
return (serverFilePath, relativePath);
}
// 获取通用文档存放路径(excel模板 )
public static (string PhysicalPath, string RelativePath) GetCommonDocPath(IWebHostEnvironment _hostEnvironment, string fileName)
{
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
//文件类型路径处理
var uploadFolderPath = Path.Combine(rootPath, StaticData.SystemDataFolder, StaticData.DataTemplate);
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
var relativePath = $"/{StaticData.IRaCISDataFolder}/{StaticData.SystemDataFolder}/{StaticData.DataTemplate}/{trustedFileNameForFileStorage}";
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
return (serverFilePath, relativePath);
}
//获取系统通知文档存放路径
public static (string PhysicalPath, string RelativePath) GetSystemNoticePath(IWebHostEnvironment _hostEnvironment, string fileName)
{
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
//文件类型路径处理
var uploadFolderPath = Path.Combine(rootPath, StaticData.SystemDataFolder, StaticData.NoticeAttachment);
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
var relativePath = $"/{StaticData.IRaCISDataFolder}/{StaticData.SystemDataFolder}/{StaticData.NoticeAttachment}/{trustedFileNameForFileStorage}";
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
return (serverFilePath, relativePath);
}
// 获取一致性核查路径
public static (string PhysicalPath, string RelativePath) GetTrialCheckFilePath(IWebHostEnvironment _hostEnvironment, string fileName,Guid trialId)
{
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
//上传根路径
string uploadFolderPath = Path.Combine(rootPath, StaticData.TrialDataFolder, trialId.ToString(), "CheckExcel");
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
//存放核对表
var (trustedFileNameForFileStorage, realFileName) = FileStoreHelper.GetStoreFileName(fileName);
var relativePath = $"/{StaticData.IRaCISDataFolder}/{StaticData.TrialDataFolder}/{trialId}/CheckExcel/{trustedFileNameForFileStorage}";
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
return (serverFilePath, relativePath);
}
//获取临床数据存放路径
public static (string PhysicalPath, string RelativePath,string FileRealName) GetClinicalDataPath(IWebHostEnvironment _hostEnvironment, string fileName,Guid trialId,Guid siteId,Guid subjectId,Guid subjectVisitId)
{
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
string uploadFolderPath = Path.Combine(rootPath, StaticData.TrialDataFolder, trialId.ToString(),siteId.ToString(), subjectId.ToString(), subjectVisitId.ToString(), StaticData.TreatmenthistoryFolder);
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
var relativePath = $"/{StaticData.IRaCISDataFolder}/{StaticData.TrialDataFolder}/{trialId}/{siteId}/{subjectId}/{subjectVisitId}/{StaticData.TreatmenthistoryFolder}/{trustedFileNameForFileStorage}";
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
return (serverFilePath, relativePath, fileRealName);
}
//获取非dicom文件存放路径
public static (string PhysicalPath, string RelativePath, string FileRealName) GetNoneDicomFilePath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId)
{
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
string uploadFolderPath = Path.Combine(rootPath, StaticData.TrialDataFolder, trialId.ToString(), siteId.ToString(), subjectId.ToString(), subjectVisitId.ToString(), StaticData.NoneDicomFolder);
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
var relativePath = $"/{StaticData.IRaCISDataFolder}/{StaticData.TrialDataFolder}/{trialId}/{siteId}/{subjectId}/{subjectVisitId}/{StaticData.NoneDicomFolder}/{trustedFileNameForFileStorage}";
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
return (serverFilePath, relativePath, fileRealName);
}
// 获取医生通用文件存放路径
public static (string PhysicalPath, string RelativePath) GetDoctorOrdinaryFilePath(IWebHostEnvironment _hostEnvironment, string fileName,Guid doctorId,string attachmentType)
{
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
//文件类型路径处理
var uploadFolderPath = Path.Combine(rootPath, "UploadFile", doctorId.ToString(), attachmentType);
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
var relativePath = $"/{StaticData.IRaCISDataFolder}/UploadFile/{doctorId}/{attachmentType}/{trustedFileNameForFileStorage}";
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
return (serverFilePath, relativePath);
}
public static (string PhysicalPath, string RelativePath) GetNonDoctorFilePath(IWebHostEnvironment _hostEnvironment, string fileName, string attachmentType)
{
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
//文件类型路径处理
var uploadFolderPath = Path.Combine(rootPath, "UploadFile", attachmentType);
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
var relativePath = $"/{StaticData.IRaCISDataFolder}/UploadFile/{attachmentType}/{trustedFileNameForFileStorage}";
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
return (serverFilePath, relativePath);
}
}
@@ -8,7 +8,6 @@ namespace IRaCIS.Core.Application.Helper;
public static class SendEmailHelper
{
public static async Task SendEmailAsync(MimeMessage messageToSend, EventHandler<MessageSentEventArgs>? messageSentSuccess = null)
{
using (var smtp = new MailKit.Net.Smtp.SmtpClient())
@@ -422,6 +422,14 @@
<param name="trialExternalUserId"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Helper.FileStoreHelper.WriteFileAsync(System.IO.Stream,System.String)">
<summary>
写文件导到磁盘
</summary>
<param name="stream"></param>
<param name="path">文件保存路径</param>
<returns></returns>
</member>
<member name="T:IRaCIS.Core.Application.ViewModel.CommonDocumentView">
<summary> CommonDocumentView 列表视图模型 </summary>
</member>
@@ -678,15 +686,6 @@
受试者临床信息
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Contracts.ClinicalDataService.UploadVisitClinicalData(Microsoft.AspNetCore.Http.IFormCollection,System.Guid,Microsoft.AspNetCore.Hosting.IWebHostEnvironment)">
<summary>
上传临床数据
</summary>
<param name="formCollection"></param>
<param name="subjectVisitId"></param>
<param name="_hostEnvironment"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Contracts.ClinicalDataService.GetSubjectVisitClinicalData(System.Guid)">
<summary>
获取访视+受试者级别的数据
@@ -830,15 +829,6 @@
<param name="noneDicomStudyId"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Contracts.NoneDicomStudyService.UploadNoneDicomFile(Microsoft.AspNetCore.Http.IFormCollection,System.Guid,System.Guid)">
<summary>
上传非Dicom 文件 支持压缩包
</summary>
<param name="formCollection"></param>
<param name="subjectVisitId"></param>
<param name="noneDicomStudyId"></param>
<returns></returns>
</member>
<member name="T:IRaCIS.Core.Application.Contracts.QCQuestionConfigureService">
<summary>
系统QC 问题管理
@@ -1556,14 +1546,6 @@
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Image.QA.QCOperationService.UploadVisitCheckExcel(Microsoft.AspNetCore.Http.IFormFile,System.Guid)">
<summary>
一致性核查 excel上传 支持三种格式
</summary>
<param name="file"></param>
<param name="trialId"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Image.QA.QCOperationService.AddOrUpdateQCQuestionAnswerList(IRaCIS.Core.Application.Contracts.DTO.QCQuestionAnswerCommand[],System.Guid,System.Guid,IRaCIS.Core.Domain.Share.TrialQCProcess,IRaCIS.Core.Domain.Share.CurrentQC)">
<summary>
添加或者更新 QC核对问题列表 两个人不能同时操作,就算意外进去了,提交数据,也不会覆盖前一个人数据, 后台已经做好判断
@@ -1751,19 +1733,6 @@
<param name="trialConfig"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.TrialConfigService.VerifySignature(IRaCIS.Core.Application.Contracts.SignDTO)">
<summary>
签名认证 +
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.TrialConfigService.MakeSignEffective(System.Guid)">
<summary>
业务接口操作成功后, 让签署数据生效
</summary>
<param name="signId"></param>
<returns></returns>
</member>
<member name="T:IRaCIS.Core.Application.Triggers.AddVisitPlanTrigger">
<summary>
添加访视计划 要给改项目下的所有Subject 添加该访视
@@ -17,7 +17,7 @@ namespace IRaCIS.Application.Interfaces
DicomTrialSiteSubjectInfo GetSaveToDicomInfo(Guid subjctVisitId);
void GetHasUploadSeriesAndInstance(Guid studyId, ref List<string> seriesInstanceUidList, ref List<string> instanceUidList);
(List<string> SeriesInstanceUid, List<string> SopInstanceUid) GetHasUploadSeriesAndInstance(Guid studyId);
void UploadOrReUploadNeedTodo(ArchiveStudyCommand archiveStudyCommand, List<Guid> archiveStudyIds, ref DicomArchiveResult reusult, StudyMonitor monitor);
@@ -26,7 +26,7 @@ namespace IRaCIS.Application.Services
private static string _fileStorePath = string.Empty;
private readonly IRepository<StudyMonitor> _dicomStudyMonitorRepository;
@@ -44,7 +44,7 @@ namespace IRaCIS.Application.Services
{
_dicomStudyMonitorRepository = dicomStudyMonitorRepository;
_userInfo = userInfo;
_studyRepository = studyRepository;
@@ -72,14 +72,16 @@ namespace IRaCIS.Application.Services
return info;
}
public void GetHasUploadSeriesAndInstance(Guid studyId, ref List<string> seriesInstanceUidList, ref List<string> sopInstanceUidList)
public (List<string> SeriesInstanceUid, List<string> SopInstanceUid) GetHasUploadSeriesAndInstance(Guid studyId)
{
seriesInstanceUidList = _dicomSeriesRepository.Where(t => t.StudyId == studyId).Select(t => t.SeriesInstanceUid).ToList();
var seriesInstanceUidList = _dicomSeriesRepository.Where(t => t.StudyId == studyId).Select(t => t.SeriesInstanceUid).ToList();
sopInstanceUidList = _dicomInstanceRepository.Where(t => t.StudyId == studyId).Select(t => t.SopInstanceUid).ToList();
var sopInstanceUidList = _dicomInstanceRepository.Where(t => t.StudyId == studyId).Select(t => t.SopInstanceUid).ToList();
return (seriesInstanceUidList, sopInstanceUidList);
}
public void UploadOrReUploadNeedTodo(ArchiveStudyCommand archiveStudyCommand, List<Guid> archiveStudyIds, ref DicomArchiveResult result,StudyMonitor monitor)
public void UploadOrReUploadNeedTodo(ArchiveStudyCommand archiveStudyCommand, List<Guid> archiveStudyIds, ref DicomArchiveResult result, StudyMonitor monitor)
{
@@ -150,7 +152,7 @@ namespace IRaCIS.Application.Services
_ = _dicomStudyMonitorRepository.AddAsync(monitor).Result;
_ = _studyRepository.SaveChangesAsync().Result;
@@ -4,15 +4,8 @@ using IRaCIS.Core.Application.Service.Inspection.DTO;
using IRaCIS.Core.Application.Service.Inspection.Interface;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Panda.DynamicWebApi.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Service.Inspection
{
@@ -4,14 +4,8 @@
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//--------------------------------------------------------------------
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Hosting;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Application.Service.Verify;
using Microsoft.AspNetCore.Authorization;
using IRaCIS.Core.Application.Auth;
namespace IRaCIS.Core.Application.Contracts
{
@@ -44,63 +38,6 @@ namespace IRaCIS.Core.Application.Contracts
/// <summary>
/// 上传临床数据
/// </summary>
/// <param name="formCollection"></param>
/// <param name="subjectVisitId"></param>
/// <param name="_hostEnvironment"></param>
/// <returns></returns>
[HttpPost("{trialId:guid}/{subjectVisitId:guid}")]
[DisableRequestSizeLimit]
[Authorize(Policy = IRaCISPolicy.CRC)]
public async Task<IResponseOutput> UploadVisitClinicalData(IFormCollection formCollection, Guid subjectVisitId, [FromServices] IWebHostEnvironment _hostEnvironment)
{
await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId);
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
//上传根路径
var _fileStorePath = Path.Combine(rootPath, StaticData.TrialDataFolder);
var sv = _repository.Where<SubjectVisit>(t => t.Id == subjectVisitId).Select(t => new { t.TrialId, t.SiteId, t.SubjectId }).FirstOrDefault().IfNullThrowException();
string uploadFolderPath = Path.Combine(_fileStorePath, sv.TrialId.ToString(),
sv.SiteId.ToString(), sv.SubjectId.ToString(), subjectVisitId.ToString(), StaticData.TreatmenthistoryFolder);
if (!Directory.Exists(uploadFolderPath))
{
Directory.CreateDirectory(uploadFolderPath);
}
foreach (IFormFile file in formCollection.Files)
{
var (trustedFileNameForFileStorage, fileName) = FileStoreHelper.GetStoreFileName(file.FileName);
var relativePath = $"/{StaticData.IRaCISDataFolder}/{StaticData.TrialDataFolder}/{sv.TrialId}/{sv.SiteId}/{sv.SubjectId}/{subjectVisitId}/{StaticData.TreatmenthistoryFolder}/{trustedFileNameForFileStorage}";
var filePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
using (FileStream fs = System.IO.File.Create(filePath))
{
await file.CopyToAsync(fs);
await fs.FlushAsync();
}
//插入临床pdf 路径
await _previousPdfRepository.AddAsync(new PreviousPDF() { SubjectVisitId = subjectVisitId, Path = relativePath, FileName = fileName });
}
await _repository.SaveChangesAsync();
return ResponseOutput.Ok();
}
/// <summary>
/// 获取访视+受试者级别的数据
@@ -25,6 +25,6 @@ namespace IRaCIS.Core.Application.Contracts
Task<List<PreviousPDFView>> GetPreviousPDFList(Guid subjectVisitId);
Task<List<PreviousSurgeryView>> GetPreviousSurgeryList(PreviousSurgeryQuery queryPreviousSurgery);
Task<SubjectClinicalDataDto> GetSubjectVisitClinicalData(Guid subjectVisitId);
Task<IResponseOutput> UploadVisitClinicalData(IFormCollection formCollection, Guid subjectVisitId, [FromServices] IWebHostEnvironment _hostEnvironment);
//Task<IResponseOutput> UploadVisitClinicalData(IFormCollection formCollection, Guid subjectVisitId, [FromServices] IWebHostEnvironment _hostEnvironment);
}
}
@@ -18,7 +18,7 @@ namespace IRaCIS.Core.Application.Contracts
Task<List<NoneDicomStudyFileView>> GetNoneDicomStudyFileList(Guid noneDicomStudyId);
Task<List<NoneDicomStudyView>> GetNoneDicomStudyList(Guid subjectVisitId, Guid? sujectVisitId = null);
Task<List<NoneDicomStudyFileView>> GetVisitNoneDicomStudyFileList(Guid subjectVisitId);
Task<IResponseOutput> UploadNoneDicomFile(IFormCollection formCollection, Guid subjectVisitId, Guid noneDicomStudyId);
//Task<IResponseOutput> UploadNoneDicomFile(IFormCollection formCollection, Guid subjectVisitId, Guid noneDicomStudyId);
@@ -36,7 +36,7 @@ namespace IRaCIS.Core.Application.Image.QA
Task<IResponseOutput> SetVisitUrgent(Guid trialId, Guid subjectVisitId, bool setOrCancel);
Task<IResponseOutput> UpdateModality(UpdateModalityCommand updateModalityCommand);
Task<IResponseOutput> UpdateSubjectAndSVInfo(UploadSubjectAndVisitCommand command);
Task<IResponseOutput> UploadVisitCheckExcel(IFormFile file, Guid trialId);
//Task<IResponseOutput> UploadVisitCheckExcel(IFormFile file, Guid trialId);
Task<IResponseOutput> VerifyCanQCPassedOrFailed(Guid subjectVisitId);
@@ -4,20 +4,10 @@
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//--------------------------------------------------------------------
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using IRaCIS.Core.Domain.Share;
using SharpCompress.Archives;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Service.Inspection.Interface;
using Nito.AsyncEx;
using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Infrastructure;
using Microsoft.Extensions.Logging;
using System.ComponentModel.DataAnnotations;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service.Verify;
using Microsoft.AspNetCore.Authorization;
using IRaCIS.Core.Application.Auth;
namespace IRaCIS.Core.Application.Contracts
{
@@ -28,39 +18,21 @@ namespace IRaCIS.Core.Application.Contracts
public class NoneDicomStudyService : BaseService, INoneDicomStudyService
{
private readonly IRepository<NoneDicomStudy> _noneDicomStudyRepository;
private readonly IHttpContextAccessor _httpContext;
private readonly IDictionaryService _dictionaryService;
private readonly IInspectionService _inspectionService;
private readonly IRepository<StudyMonitor> _studyMonitorRepository;
private readonly IRepository<NoneDicomStudyFile> _noneDicomStudyFileRepository;
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
private readonly AsyncLock _mutex = new AsyncLock();
private readonly ILogger<NoneDicomStudyService> _logger;
public NoneDicomStudyService(IRepository<NoneDicomStudy> noneDicomStudyRepository,
IHttpContextAccessor httpContext,
IDictionaryService dictionaryService,
IInspectionService inspectionService,
IRepository<StudyMonitor> studyMonitorRepository,
IRepository<NoneDicomStudyFile> noneDicomStudyFileRepository, IRepository<SubjectVisit> subjectVisitRepository, ILogger<NoneDicomStudyService> logger)
IRepository<NoneDicomStudyFile> noneDicomStudyFileRepository)
{
_noneDicomStudyRepository = noneDicomStudyRepository;
this._httpContext = httpContext;
this._dictionaryService = dictionaryService;
this._inspectionService = inspectionService;
this._studyMonitorRepository = studyMonitorRepository;
_noneDicomStudyFileRepository = noneDicomStudyFileRepository;
this._subjectVisitRepository = subjectVisitRepository;
_logger = logger;
}
[HttpGet]
public async Task<List<NoneDicomStudyView>> GetNoneDicomStudyList( [FromQuery,NotDefault] Guid subjectVisitId,Guid? nonedicomStudyId)
{
@@ -171,116 +143,5 @@ namespace IRaCIS.Core.Application.Contracts
/// <summary>
/// 上传非Dicom 文件 支持压缩包
/// </summary>
/// <param name="formCollection"></param>
/// <param name="subjectVisitId"></param>
/// <param name="noneDicomStudyId"></param>
/// <returns></returns>
//[DisableRequestSizeLimit]
[RequestSizeLimit(1_073_741_824)]
[HttpPost("{trialId:guid}/{subjectVisitId:guid}/{noneDicomStudyId:guid}")]
[TypeFilter(typeof(TrialResourceFilter))]
[Authorize(Policy = IRaCISPolicy.CRC)]
public async Task<IResponseOutput> UploadNoneDicomFile(IFormCollection formCollection, Guid subjectVisitId, Guid noneDicomStudyId)
{
await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId);
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
//上传根路径
var _fileStorePath = Path.Combine(rootPath, StaticData.TrialDataFolder);
var sv = (await _repository.Where<SubjectVisit>(t => t.Id == subjectVisitId).Select(t => new { t.TrialId, t.SiteId, t.SubjectId }).FirstOrDefaultAsync()).IfNullThrowConvertException();
string uploadFolderPath = Path.Combine(_fileStorePath, sv.TrialId.ToString(), sv.SiteId.ToString(), sv.SubjectId.ToString(), subjectVisitId.ToString(), StaticData.NoneDicomFolder);
if (!Directory.Exists(uploadFolderPath))
{
Directory.CreateDirectory(uploadFolderPath);
}
var startTime = DateTime.Now;
foreach (IFormFile file in formCollection.Files)
{
if (file.FileName.Contains(".Zip", StringComparison.OrdinalIgnoreCase) || file.FileName.Contains(".rar", StringComparison.OrdinalIgnoreCase))
{
var archive = ArchiveFactory.Open(file.OpenReadStream());
foreach (var entry in archive.Entries)
{
if (!entry.IsDirectory)
{
DealCompressFile(entry, sv, subjectVisitId, noneDicomStudyId, uploadFolderPath);
}
}
}
else
{
var (trustedFileNameForFileStorage, fileName) = FileStoreHelper.GetStoreFileName(file.FileName);
var relativePath = $"/{StaticData.TrialDataFolder}/{sv.TrialId}/{sv.SiteId}/{sv.SubjectId}/{subjectVisitId}/{StaticData.NoneDicomFolder}/{trustedFileNameForFileStorage}";
var filePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
using (FileStream fs = System.IO.File.Create(filePath))
{
await file.CopyToAsync(fs);
await fs.FlushAsync();
}
await _noneDicomStudyFileRepository.AddAsync(new NoneDicomStudyFile() { FileName = fileName, Path = relativePath, NoneDicomStudyId = noneDicomStudyId });
}
}
// 上传非Dicom 后 将状态改为待提交 分为普通上传 和QC后重传 普通上传时才改为待提交
await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.Id == subjectVisitId && t.SubmitState == SubmitStateEnum.None, u => new SubjectVisit() { SubmitState = SubmitStateEnum.ToSubmit });
var studyCode = await _noneDicomStudyRepository.Where(t => t.Id == noneDicomStudyId).Select(t => t.StudyCode).FirstOrDefaultAsync();
await _studyMonitorRepository.AddAsync(new StudyMonitor()
{
FileCount = formCollection.Files.Count,
FileSize = formCollection.Files.Sum(t => t.Length),
IsDicom = false,
IsDicomReUpload = false,
StudyId = noneDicomStudyId,
StudyCode = studyCode,
UploadStartTime = startTime,
UploadFinishedTime = DateTime.Now,
IP = _userInfo.IP,
TrialId = sv.TrialId,
SiteId = sv.SiteId,
SubjectId = sv.SubjectId,
SubjectVisitId = subjectVisitId,
});
await _noneDicomStudyFileRepository.SaveChangesAsync();
return ResponseOutput.Ok(/*list*/);
}
private async void DealCompressFile(IArchiveEntry entry, dynamic sv, Guid subjectVisitId, Guid noneDicomStudyId, string uploadFolderPath)
{
var (trustedFileNameForFileStorage, fileName) = FileStoreHelper.GetStoreFileName(entry.Key);
var relativePath = $"/{StaticData.IRaCISDataFolder}/{StaticData.TrialDataFolder}/{sv.TrialId}/{sv.SiteId}/{sv.SubjectId}/{subjectVisitId}/{StaticData.NoneDicomFolder}/{trustedFileNameForFileStorage}";
var filePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
entry.WriteToFile(filePath);
await _noneDicomStudyFileRepository.AddAsync(new NoneDicomStudyFile() { FileName = fileName, Path = relativePath, NoneDicomStudyId = noneDicomStudyId });
}
}
}
@@ -1,28 +1,18 @@
using Hangfire;
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
using IRaCIS.Core.Application.BackGroundJob;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Domain.Share;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using System.Net.Http.Headers;
using Microsoft.AspNetCore.Http;
using MiniExcelLibs;
using ExcelDataReader;
using System.Text;
using System.Data;
using Microsoft.AspNetCore.Authorization;
using WinSCP;
using Magicodes.ExporterAndImporter.Excel;
using Newtonsoft.Json;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Application.Service.Inspection.DTO;
using Nito.AsyncEx;
using System.ComponentModel.DataAnnotations;
using IRaCIS.Core.Application.Auth;
using IRaCIS.Core.Application.Helper;
namespace IRaCIS.Core.Application.Image.QA
{
@@ -39,16 +29,12 @@ namespace IRaCIS.Core.Application.Image.QA
private readonly IRepository<QCChallengeDialog> _qCChallengeDialogrepository;
private readonly IRepository<CheckChallengeDialog> _checkChallengeDialogrepository;
private readonly IRepository<Trial> _trialRepository;
private readonly IRepository<ConsistencyCheckFile> _consistencyCheckFileRepository;
private readonly IMediator _mediator;
private readonly AsyncLock _mutex = new AsyncLock();
public QCOperationService(DicomFileStoreHelper dicomFileStoreHelper, IRepository<SubjectVisit> subjectVisitRepository,
IRepository<QCChallenge> qcChallengeRepository,
IRepository<Trial> trialRepository,
IRepository<ConsistencyCheckFile> consistencyCheckFileRepository,
IMediator mediator,
IRepository<DicomStudy> dicomStudyRepository,
IRepository<DicomSeries> dicomSeriesrepository,
IRepository<Subject> subjectRepository,
@@ -64,9 +50,7 @@ namespace IRaCIS.Core.Application.Image.QA
this._subjectRepository = subjectRepository;
this._qCChallengeDialogrepository = qCChallengeDialogrepository;
this._checkChallengeDialogrepository = checkChallengeDialogrepository;
_mediator = mediator;
_trialRepository = trialRepository;
this._consistencyCheckFileRepository = consistencyCheckFileRepository;
}
#region QC质疑
@@ -519,229 +503,6 @@ namespace IRaCIS.Core.Application.Image.QA
}
/// <summary>
/// 一致性核查 excel上传 支持三种格式
/// </summary>
/// <param name="file"></param>
/// <param name="trialId"></param>
/// <returns></returns>
[HttpPost("{trialId:guid}")]
[TypeFilter(typeof(TrialResourceFilter))]
[Authorize(Policy = IRaCISPolicy.PM_APM)]
public async Task<IResponseOutput> UploadVisitCheckExcel(IFormFile file, Guid trialId)
{
//if (_userInfo.UserTypeEnumInt != (int)UserTypeEnum.ProjectManager && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.APM)
//{
// return ResponseOutput.NotOk("只有PM/APM具有操作权限!");
//}
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
var fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.ToString().Trim('"').ToLower();
if (!fileName.EndsWith(".xlsx") && !fileName.EndsWith(".csv") && !fileName.EndsWith(".xls"))
{
return ResponseOutput.NotOk("支持.xlsx、.xls、.csv格式的文件上传。");
}
//上传根路径
string uploadFolderPath = Path.Combine(rootPath,StaticData.TrialDataFolder, trialId.ToString(), "CheckExcel");
if (!Directory.Exists(uploadFolderPath))
{
Directory.CreateDirectory(uploadFolderPath);
}
//存放核对表
var (trustedFileNameForFileStorage, realFileName) = FileStoreHelper.GetStoreFileName(fileName);
var filePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
using (FileStream fs = System.IO.File.Create(filePath))
{
await file.CopyToAsync(fs);
await fs.FlushAsync();
}
//获取Excel表内容
var config = new MiniExcelLibs.Csv.CsvConfiguration()
{
StreamReaderFunc = (stream) => new StreamReader(stream, Encoding.GetEncoding("gb2312"))
};
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>(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();
}
else if (fileName.EndsWith(".csv"))
{
#region MiniExcel读取 xlsx Magicodes验证数据
//因为csv 需要加配置文件 不然都是null
etcCheckList = MiniExcel.Query<CheckViewModel>(filePath, null, configuration: config).ToList();
var csVToXlsxPath = Path.Combine(uploadFolderPath, DateTime.Now.ToString("yyyy-MM-dd-hh-mm-ss") + Path.GetFileNameWithoutExtension(fileName) + ".xlsx");
await MiniExcel.SaveAsAsync(csVToXlsxPath, etcCheckList, excelType: ExcelType.XLSX);
var Importer = new ExcelImporter();
var import = await Importer.Import<CheckViewModel>(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(filePath, 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
}
}
}
//etcCheckList = etcCheckList.Where(t=>)
if (etcCheckList == null || etcCheckList.Count == 0)
{
return ResponseOutput.NotOk("请保证上传数据符合模板文件中的样式,且存在有效数据。");
}
else
{
//处理Excel 有时只是清除某些行的数据 读取也会读到数据,只是数据是null 后面处理的时候转为字符串为报错
etcCheckList.ForEach(t =>
{
t.Modality = t.Modality ?? string.Empty;
t.SiteCode = t.SiteCode ?? string.Empty;
t.SubjectCode = t.SubjectCode ?? string.Empty;
t.VisitName = t.VisitName ?? string.Empty;
t.StudyDate = t.StudyDate ?? string.Empty;
});
var dt = DateTime.Now;
etcCheckList = etcCheckList.Where(t => !(t.Modality == string.Empty && t.SiteCode == string.Empty && t.SubjectCode == string.Empty && t.VisitName == string.Empty && t.StudyDate == string.Empty && DateTime.TryParse(t.StudyDate, out dt))).ToList();
if (etcCheckList.Count == 0)
{
return ResponseOutput.NotOk("请保证上传数据符合模板文件中的样式,且存在有效数据。");
}
}
await _consistencyCheckFileRepository.AddAsync(new ConsistencyCheckFile()
{
TrialId = trialId,
CreateTime = DateTime.Now,
FileName = fileName,
FilePath = filePath,
RelativePaths = filePath.Replace(rootPath, ""),
CreateUserId = _userInfo.Id
});
//new()
//{
// TrialId = trialId,
// CreateTime = DateTime.Now,
// FileName = fileName,
// FilePath = filePath,
// CreateUser =
// RelativePaths = filePath.Replace(rootPath, "");
//};
await _mediator.Send(new ConsistencyVerificationRequest() { ETCList = etcCheckList, TrialId = trialId });
return ResponseOutput.Ok();
}
#endregion
@@ -349,94 +349,5 @@ namespace IRaCIS.Core.Application
#region
[Obsolete]
[HttpPost("{trialId:guid}/{type}")]
public async Task<IResponseOutput> UploadTrialFile(IFormFile file, string type, Guid trialId, [FromServices] IWebHostEnvironment _hostEnvironment)
{
var rootPath = Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\')).IfNullThrowException().FullName;
//上传根路径
var _fileStorePath = Path.Combine(rootPath, StaticData.TrialDataFolder);
//文件类型路径处理
var uploadFolderPath = Path.Combine(_fileStorePath, trialId.ToString(), type);
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
var realName = file.FileName;
var fileNameEX = Path.GetExtension(realName);
var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileNameEX;
var relativePath = $"/{StaticData.TrialDataFolder}/{trialId}/{type}/{trustedFileNameForFileStorage}";
var filePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
using (FileStream fs = System.IO.File.Create(filePath))
{
await file.CopyToAsync(fs);
fs.Flush();
}
return ResponseOutput.Ok(new
{
FilePath = relativePath,
FullFilePath = relativePath + "?access_token=" + _userInfo.UserToken
});
}
/// <summary>
/// 签名认证 +
/// </summary>
/// <returns></returns>
[HttpPost]
[Obsolete]
public async Task<IResponseOutput> VerifySignature(SignDTO signDTO)
{
var user = await _repository.FirstOrDefaultAsync<User>(u => u.UserName == signDTO.UserName && u.Password == signDTO.PassWord);
if (user == null)
{
return ResponseOutput.NotOk("密码错误。");
}
else if (user.Status == UserStateEnum.Disable)
{
return ResponseOutput.NotOk("该用户已被禁止使用。");
}
//if (signDTO.IsAddSignData)
//{
// 记录签名信息
var add = await _repository.AddAsync(_mapper.Map<TrialSign>(signDTO));
await _repository.SaveChangesAsync();
return ResponseOutput.Ok(add.Id);
//}
//return ResponseOutput.Ok();
}
/// <summary>
/// 业务接口操作成功后, 让签署数据生效
/// </summary>
/// <param name="signId"></param>
/// <returns></returns>
[HttpPut("{signId:guid}")]
[Obsolete]
public async Task<IResponseOutput> MakeSignEffective(Guid signId)
{
var success = await _repository.BatchUpdateAsync<TrialSign>(t => t.Id == signId, u => new TrialSign() { IsCompleted = true });
return ResponseOutput.Result(success);
}
#endregion
}
}