320 lines
12 KiB
C#
320 lines
12 KiB
C#
using IRaCIS.Core.Domain.Share;
|
||
using IRaCIS.Core.Infrastructure;
|
||
using Microsoft.AspNetCore.Hosting;
|
||
using Newtonsoft.Json.Linq;
|
||
using System.Globalization;
|
||
using System.Text.RegularExpressions;
|
||
|
||
namespace IRaCIS.Core.Application.Helper;
|
||
|
||
public static class FileStoreHelper
|
||
{
|
||
|
||
//处理文件名 压缩包,或者目录类的 会带上相对路径
|
||
public static (string TrustedFileNameForFileStorage, string RealName) GetStoreFileName(string fileName, bool isChangeToPdfFormat = false)
|
||
{
|
||
|
||
//带目录层级,需要后端处理前端的路径
|
||
if (fileName.Contains("\\"))
|
||
{
|
||
fileName = fileName.Split("\\").Last();
|
||
}
|
||
|
||
if (fileName.Contains("/"))
|
||
{
|
||
fileName = fileName.Split("/").Last();
|
||
}
|
||
|
||
var matchResult = Regex.Match(fileName, @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||
|
||
//如果有guid
|
||
if (matchResult.Success)
|
||
{
|
||
fileName = fileName.Replace($"{matchResult.Value}", "");
|
||
}
|
||
|
||
|
||
var trustedFileNameForFileStorage = string.Empty;
|
||
|
||
if (isChangeToPdfFormat == false)
|
||
{
|
||
trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileName;
|
||
|
||
}
|
||
else
|
||
{
|
||
trustedFileNameForFileStorage = Guid.NewGuid().ToString() + Path.GetFileNameWithoutExtension(fileName) + ".pdf";
|
||
}
|
||
|
||
return (trustedFileNameForFileStorage, fileName);
|
||
}
|
||
|
||
//API vue 部署目录
|
||
public static string GetIRaCISRootPath(IWebHostEnvironment _hostEnvironment)
|
||
{
|
||
string parentDirectory = Path.GetFullPath(Path.Combine(_hostEnvironment.ContentRootPath, ".."));
|
||
|
||
return parentDirectory;
|
||
|
||
}
|
||
|
||
|
||
//获取环境存储根目录
|
||
public static string GetIRaCISRootDataFolder(IWebHostEnvironment _hostEnvironment)
|
||
{
|
||
var rootPath = GetIRaCISRootPath(_hostEnvironment);
|
||
|
||
var rootFolder = Path.Combine(rootPath, StaticData.Folder.IRaCISDataFolder);
|
||
|
||
return rootFolder;
|
||
}
|
||
|
||
//根据相对路径 获取具体文件物理地址
|
||
public static string GetPhysicalFilePath(IWebHostEnvironment _hostEnvironment, string relativePath)
|
||
{
|
||
var rootPath = GetIRaCISRootPath(_hostEnvironment);
|
||
|
||
var physicalFilePath = Path.Combine(rootPath, relativePath.TrimStart('/'));
|
||
|
||
return physicalFilePath;
|
||
}
|
||
|
||
|
||
#region 修改后留存
|
||
|
||
|
||
public static (string PhysicalPath, string RelativePath) GetSystemFileUploadPath(IWebHostEnvironment _hostEnvironment, string templateFolderName, string fileName)
|
||
{
|
||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||
|
||
//文件类型路径处理
|
||
var uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.SystemDataFolder, templateFolderName);
|
||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
||
|
||
|
||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
||
|
||
|
||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.SystemDataFolder}/{templateFolderName}/{trustedFileNameForFileStorage}";
|
||
|
||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
||
|
||
return (serverFilePath, relativePath);
|
||
}
|
||
|
||
public static (string PhysicalPath, string RelativePath) GetOtherFileUploadPath(IWebHostEnvironment _hostEnvironment, string templateFolderName, string fileName)
|
||
{
|
||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||
|
||
//文件类型路径处理
|
||
var uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.OtherDataFolder, templateFolderName);
|
||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
||
|
||
|
||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
||
|
||
|
||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.OtherDataFolder}/{templateFolderName}/{trustedFileNameForFileStorage}";
|
||
|
||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
||
|
||
return (serverFilePath, relativePath);
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
|
||
//通过编码获取通用文档具体物理路径
|
||
|
||
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);
|
||
|
||
var isEn_US = CultureInfo.CurrentCulture.Name != StaticData.CultureInfo.zh_CN;
|
||
if (doc == null)
|
||
{
|
||
//---数据库没有找到对应的数据模板文件,请联系系统运维人员。
|
||
throw new BusinessValidationFailedException(I18n.T("FileStore_TemplateFileNotFound"));
|
||
}
|
||
|
||
var filePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, doc.Path);
|
||
|
||
if (!System.IO.File.Exists(filePath))
|
||
{
|
||
//---数据模板文件存储路径上未找对应文件,请联系系统运维人员。
|
||
throw new BusinessValidationFailedException(I18n.T("FileStore_TemplateFileStoragePathInvalid"));
|
||
}
|
||
|
||
return (filePath, isEn_US ? doc.Name.Trim('/') : doc.NameCN.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;
|
||
}
|
||
|
||
|
||
// 获取通用文档存放路径(excel模板 )
|
||
|
||
public static (string PhysicalPath, string RelativePath) GetCommonDocPath(IWebHostEnvironment _hostEnvironment, string fileName)
|
||
{
|
||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||
|
||
//文件类型路径处理
|
||
var uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.SystemDataFolder, StaticData.Folder.DataTemplate);
|
||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
||
|
||
|
||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
||
|
||
|
||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.SystemDataFolder}/{StaticData.Folder.DataTemplate}/{trustedFileNameForFileStorage}";
|
||
|
||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
||
|
||
return (serverFilePath, relativePath);
|
||
}
|
||
|
||
// 获取 入组确认 PD 进展发送邮件Word|PDF 存放路径
|
||
|
||
public static (string PhysicalPath, string RelativePath, string FileRealName) GetSubjectEnrollConfirmOrPDEmailPath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid trialSiteId, Guid subjectId, bool isChangeToPdfFormat = false)
|
||
{
|
||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||
|
||
string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), trialSiteId.ToString(), subjectId.ToString());
|
||
|
||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
||
|
||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName, isChangeToPdfFormat);
|
||
|
||
|
||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{trialSiteId}/{subjectId}/{trustedFileNameForFileStorage}";
|
||
|
||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
||
|
||
return (serverFilePath, relativePath, fileRealName);
|
||
}
|
||
|
||
|
||
public static string GetSubjectVisitDicomFolderPhysicalPath(IWebHostEnvironment _hostEnvironment, Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId)
|
||
{
|
||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||
|
||
return Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteId.ToString(), subjectId.ToString(), subjectVisitId.ToString(), StaticData.Folder.DicomFolder);
|
||
}
|
||
|
||
public static (string PhysicalPath, string RelativePath) GetDicomInstanceFilePath(IWebHostEnvironment _hostEnvironment, Guid trialId, Guid subjectId, Guid subjectVisitId, Guid studyId, Guid instanceId)
|
||
{
|
||
#region 切换存储前
|
||
//var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||
#endregion
|
||
var rootPath = Path.Combine(FileStoreHelper.GetBestStoreDisk(_hostEnvironment), StaticData.Folder.IRaCISDataFolder);
|
||
|
||
|
||
|
||
//加入访视层级 和Data
|
||
var path = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(),
|
||
subjectId.ToString(), subjectVisitId.ToString(), StaticData.Folder.DicomFolder, studyId.ToString());
|
||
|
||
if (!Directory.Exists(path))
|
||
{
|
||
Directory.CreateDirectory(path);
|
||
}
|
||
|
||
var physicalPath = Path.Combine(path, instanceId.ToString());
|
||
|
||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{subjectId}/{subjectVisitId}/{StaticData.Folder.DicomFolder}/{studyId}/{instanceId}";
|
||
|
||
//var physicalPath = Path.Combine(path, instanceId.ToString() + ".dcm");
|
||
|
||
//var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{siteId}/{subjectId}/{subjectVisitId}/{StaticData.Folder.DicomFolder}/{studyId}/{instanceId}.dcm";
|
||
|
||
return (physicalPath, relativePath);
|
||
}
|
||
|
||
public static string GetBestStoreDisk(IWebHostEnvironment _hostEnvironment)
|
||
{
|
||
|
||
var json = File.ReadAllText(Path.Combine(_hostEnvironment.ContentRootPath, "appsettings.json"));
|
||
|
||
JObject jsonObject = (JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load })).IfNullThrowException();
|
||
|
||
int switchingRatio = 80;
|
||
|
||
try
|
||
{
|
||
switchingRatio = (int)jsonObject["IRaCISImageStore"]["SwitchingRatio"];
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
|
||
//---解析Json文件配置出现问题
|
||
throw new BusinessValidationFailedException(I18n.T("SysMon_JsonConfig") + e.Message);
|
||
}
|
||
|
||
//默认存储的路径
|
||
var defaultStoreRootFolder = FileStoreHelper.GetIRaCISRootPath(_hostEnvironment);
|
||
|
||
|
||
DriveInfo defaultDrive = new DriveInfo(Path.GetPathRoot(defaultStoreRootFolder));
|
||
|
||
var drives = DriveInfo.GetDrives().Where(t => !t.Name.Contains("C") && !t.Name.Contains("c"))
|
||
.Where(d => d.DriveType == DriveType.Fixed && d.IsReady)
|
||
//剩余空间最多的
|
||
.OrderByDescending(d => d.AvailableFreeSpace)
|
||
|
||
//存储空间相同,则按照按照总空间从大到小排序
|
||
.ThenByDescending(d => d.TotalSize - d.TotalFreeSpace);
|
||
|
||
var bestDrive = drives.FirstOrDefault();
|
||
var bestStoreRootFolder = string.Empty;
|
||
|
||
//仅仅只有C 盘
|
||
if (bestDrive == null || ((double)(defaultDrive.TotalSize - defaultDrive.TotalFreeSpace) / defaultDrive.TotalSize) * 100 < switchingRatio)
|
||
{
|
||
bestStoreRootFolder = defaultStoreRootFolder;
|
||
}
|
||
else
|
||
{
|
||
bestStoreRootFolder = Path.Combine(bestDrive?.RootDirectory.FullName, _hostEnvironment.EnvironmentName);
|
||
}
|
||
|
||
if (!Directory.Exists(bestStoreRootFolder))
|
||
{
|
||
Directory.CreateDirectory(bestStoreRootFolder);
|
||
}
|
||
|
||
return bestStoreRootFolder;
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
}
|
||
|