diff --git a/IRaCIS.Core.API/IRaCIS.Core.API.xml b/IRaCIS.Core.API/IRaCIS.Core.API.xml
index 068efa5a9..061f40bcc 100644
--- a/IRaCIS.Core.API/IRaCIS.Core.API.xml
+++ b/IRaCIS.Core.API/IRaCIS.Core.API.xml
@@ -29,7 +29,7 @@
-
+
系统用户登录接口[New]
@@ -41,7 +41,7 @@
新记录Id
-
+
添加或更新工作量[AUTH]
diff --git a/IRaCIS.Core.Application/BaseService.cs b/IRaCIS.Core.Application/BaseService.cs
index 8adf71179..c153e02d4 100644
--- a/IRaCIS.Core.Application/BaseService.cs
+++ b/IRaCIS.Core.Application/BaseService.cs
@@ -10,7 +10,7 @@ using Panda.DynamicWebApi.Attributes;
using System.Diagnostics.CodeAnalysis;
using ZiggyCreatures.Caching.Fusion;
-namespace IRaCIS.Core.Application
+namespace IRaCIS.Core.Application.Service
{
#pragma warning disable CS8618
diff --git a/IRaCIS.Core.Application/BusinessFilter/GlobalExceptionHandler.cs b/IRaCIS.Core.Application/BusinessFilter/GlobalExceptionHandler.cs
index b8f82f8d5..70688e7e2 100644
--- a/IRaCIS.Core.Application/BusinessFilter/GlobalExceptionHandler.cs
+++ b/IRaCIS.Core.Application/BusinessFilter/GlobalExceptionHandler.cs
@@ -3,42 +3,41 @@ using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
-namespace IRaCIS.Core.Application.BusinessFilter
+namespace IRaCIS.Core.Application.BusinessFilter;
+
+
+///
+/// 不生效,不知道为啥
+///
+public class GlobalExceptionHandler : IExceptionHandler
{
-
- ///
- /// 不生效,不知道为啥
- ///
- public class GlobalExceptionHandler : IExceptionHandler
+ private readonly ILogger _logger;
+ public GlobalExceptionHandler(ILogger logger)
+ {
+ this._logger = logger;
+ }
+ public ValueTask TryHandleAsync(
+ HttpContext httpContext,
+ Exception exception,
+ CancellationToken cancellationToken)
{
- private readonly ILogger _logger;
- public GlobalExceptionHandler(ILogger logger)
- {
- this._logger = logger;
- }
- public ValueTask TryHandleAsync(
- HttpContext httpContext,
- Exception exception,
- CancellationToken cancellationToken)
- {
- httpContext.Response.ContentType = "application/json";
+ httpContext.Response.ContentType = "application/json";
- var ex = exception;
- var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : "");
+ var ex = exception;
+ var errorInfo = $"Exception: {ex.Message}[{ex.StackTrace}]" + (ex.InnerException != null ? $" InnerException: {ex.InnerException.Message}[{ex.InnerException.StackTrace}]" : "");
- httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk($"{ex?.Message}"));
+ httpContext.Response.WriteAsJsonAsync(ResponseOutput.NotOk($"{ex?.Message}"));
- _logger.LogError(errorInfo);
+ _logger.LogError(errorInfo);
- // return true to signal that this exception is handled
- return ValueTask.FromResult(false);
- }
+ // return true to signal that this exception is handled
+ return ValueTask.FromResult(false);
}
}
diff --git a/IRaCIS.Core.Application/BusinessFilter/ModelActionFilter .cs b/IRaCIS.Core.Application/BusinessFilter/ModelActionFilter .cs
index c77dacdfa..a52ca0a52 100644
--- a/IRaCIS.Core.Application/BusinessFilter/ModelActionFilter .cs
+++ b/IRaCIS.Core.Application/BusinessFilter/ModelActionFilter .cs
@@ -4,33 +4,31 @@ using Microsoft.Extensions.Localization;
using Newtonsoft.Json;
-namespace IRaCIS.Core.Application.Filter
+namespace IRaCIS.Core.Application.Filter;
+
+
+
+public class ModelActionFilter : ActionFilterAttribute, IActionFilter
{
-
-
- public class ModelActionFilter : ActionFilterAttribute, IActionFilter
+ public IStringLocalizer _localizer;
+ public ModelActionFilter(IStringLocalizer localizer)
{
- public IStringLocalizer _localizer;
- public ModelActionFilter(IStringLocalizer localizer)
- {
- _localizer = localizer;
- }
-
- public override void OnActionExecuting(ActionExecutingContext context)
- {
- if (!context.ModelState.IsValid)
- {
-
- var validationErrors = context.ModelState
- .Keys
- .SelectMany(k => context.ModelState[k]!.Errors)
- .Select(e => e.ErrorMessage)
- .ToArray();
-
- //---提供给接口的参数无效。
- context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ModelAction_InvalidAPIParameter"] + JsonConvert.SerializeObject(validationErrors)));
- }
- }
+ _localizer = localizer;
}
+ public override void OnActionExecuting(ActionExecutingContext context)
+ {
+ if (!context.ModelState.IsValid)
+ {
+
+ var validationErrors = context.ModelState
+ .Keys
+ .SelectMany(k => context.ModelState[k]!.Errors)
+ .Select(e => e.ErrorMessage)
+ .ToArray();
+
+ //---提供给接口的参数无效。
+ context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ModelAction_InvalidAPIParameter"] + JsonConvert.SerializeObject(validationErrors)));
+ }
+ }
}
diff --git a/IRaCIS.Core.Application/BusinessFilter/ModelBinding.cs b/IRaCIS.Core.Application/BusinessFilter/ModelBinding.cs
index 94187d5d8..994d9fa09 100644
--- a/IRaCIS.Core.Application/BusinessFilter/ModelBinding.cs
+++ b/IRaCIS.Core.Application/BusinessFilter/ModelBinding.cs
@@ -2,26 +2,25 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
-namespace IRaCIS.Core.Application.Filter
+namespace IRaCIS.Core.Application.Filter;
+
+#region snippet_DisableFormValueModelBindingAttribute
+[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
+public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{
- #region snippet_DisableFormValueModelBindingAttribute
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
- public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
+ public void OnResourceExecuting(ResourceExecutingContext context)
{
- public void OnResourceExecuting(ResourceExecutingContext context)
- {
- var factories = context.ValueProviderFactories;
- //factories.RemoveType();
- factories.RemoveType();
- factories.RemoveType();
- context.HttpContext.Request.EnableBuffering();
- }
-
- public void OnResourceExecuted(ResourceExecutedContext context)
- {
- }
+ var factories = context.ValueProviderFactories;
+ //factories.RemoveType();
+ factories.RemoveType();
+ factories.RemoveType();
+ context.HttpContext.Request.EnableBuffering();
+ }
+
+ public void OnResourceExecuted(ResourceExecutedContext context)
+ {
}
- #endregion
}
+#endregion
diff --git a/IRaCIS.Core.Application/BusinessFilter/ProjectExceptionFilter.cs b/IRaCIS.Core.Application/BusinessFilter/ProjectExceptionFilter.cs
index ce2a978eb..1825c3728 100644
--- a/IRaCIS.Core.Application/BusinessFilter/ProjectExceptionFilter.cs
+++ b/IRaCIS.Core.Application/BusinessFilter/ProjectExceptionFilter.cs
@@ -5,72 +5,71 @@ using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
-namespace IRaCIS.Core.Application.Filter
+namespace IRaCIS.Core.Application.Filter;
+
+public class ProjectExceptionFilter : Attribute, IExceptionFilter
{
- public class ProjectExceptionFilter : Attribute, IExceptionFilter
+ private readonly ILogger _logger;
+
+ public IStringLocalizer _localizer;
+
+ public ProjectExceptionFilter(IStringLocalizer localizer, ILogger logger)
{
- private readonly ILogger _logger;
+ _logger = logger;
+ _localizer = localizer;
+ }
+ public void OnException(ExceptionContext context)
+ {
+ //context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
- public IStringLocalizer _localizer;
-
- public ProjectExceptionFilter(IStringLocalizer localizer, ILogger logger)
+ if (!context.ExceptionHandled)
{
- _logger = logger;
- _localizer = localizer;
- }
- public void OnException(ExceptionContext context)
- {
- //context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
-
- if (!context.ExceptionHandled)
+ if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
{
- if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
+ //---并发更新,当前不允许该操作
+ context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
+ }
+
+ if (context.Exception.GetType() == typeof(BusinessValidationFailedException))
+ {
+ var error = context.Exception as BusinessValidationFailedException;
+
+ var info = string.Empty;
+
+ if (!string.IsNullOrWhiteSpace(error!.LocalizedKey) && StaticData.Log_Locoalize_Dic.ContainsKey(error!.LocalizedKey))
{
- //---并发更新,当前不允许该操作
- context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
+ info = $"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}";
}
- if (context.Exception.GetType() == typeof(BusinessValidationFailedException))
- {
- var error = context.Exception as BusinessValidationFailedException;
- var info = string.Empty;
-
- if (!string.IsNullOrWhiteSpace(error!.LocalizedKey) && StaticData.Log_Locoalize_Dic.ContainsKey(error!.LocalizedKey))
- {
- info = $"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}";
- }
+ context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info));
- context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, "", error!.Code, localizedInfo: info));
-
-
- //warning 级别记录
- //_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}");
- }
- else if (context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException))
- {
- context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, ApiResponseCodeEnum.DataNotExist));
- }
- else
- {
- context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/)
- : (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.ProgramException));
-
- _logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace));
-
- }
-
- context.ExceptionHandled = true;//标记当前异常已经被处理过了
-
-
- //throw new Exception("test-result-exceptioin");
-
+ //warning 级别记录
+ //_logger.LogWarning($"[{error!.LocalizedKey}]:{StaticData.Log_Locoalize_Dic[error!.LocalizedKey]}");
+ }
+ else if (context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException))
+ {
+ context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, ApiResponseCodeEnum.DataNotExist));
}
else
{
- //继续
+ context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/)
+ : (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.ProgramException));
+
+ _logger.LogError(context.Exception.InnerException is null ? (context.Exception.Message + context.Exception.StackTrace) : (context.Exception.InnerException?.Message + context.Exception.InnerException?.StackTrace));
+
}
+
+ context.ExceptionHandled = true;//标记当前异常已经被处理过了
+
+
+ //throw new Exception("test-result-exceptioin");
+
+ }
+ else
+ {
+ //继续
}
}
}
diff --git a/IRaCIS.Core.Application/BusinessFilter/TrialResourceFilter.cs b/IRaCIS.Core.Application/BusinessFilter/TrialResourceFilter.cs
index 58467110b..509b6dc83 100644
--- a/IRaCIS.Core.Application/BusinessFilter/TrialResourceFilter.cs
+++ b/IRaCIS.Core.Application/BusinessFilter/TrialResourceFilter.cs
@@ -8,80 +8,124 @@ using System.Text.RegularExpressions;
using ZiggyCreatures.Caching.Fusion;
using static IRaCIS.Core.Domain.Share.StaticData;
-namespace IRaCIS.Core.Application.Filter
+namespace IRaCIS.Core.Application.Filter;
+
+///
+/// 主要为了 处理项目结束 锁库,不允许操作
+///
+public class TrialResourceFilter : Attribute, IAsyncResourceFilter
{
- ///
- /// 主要为了 处理项目结束 锁库,不允许操作
- ///
- public class TrialResourceFilter : Attribute, IAsyncResourceFilter
+ private readonly IUserInfo _userInfo;
+ private readonly IFusionCache _fusionCache;
+ public IStringLocalizer _localizer;
+ private readonly IRepository _trialRepository;
+ private readonly List _trialOptList = new List();
+
+
+ public TrialResourceFilter(IFusionCache fusionCache, IRepository trialRepository, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
{
- private readonly IUserInfo _userInfo;
- private readonly IFusionCache _fusionCache;
- public IStringLocalizer _localizer;
- private readonly IRepository _trialRepository;
- private readonly List _trialOptList = new List();
+ _fusionCache = fusionCache;
+ _userInfo = userInfo;
+ _localizer = localizer;
+ _trialRepository = trialRepository;
+ if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
+ if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
+ if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
- public TrialResourceFilter(IFusionCache fusionCache, IRepository trialRepository, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
+ }
+
+ //优先选择异步的方法
+ public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
+ {
+ // var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault();
+ //var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
+
+ #region 处理新的用户类型,不能操作项目相关接口
+
+ // 后期列举出具体的类型,其他任何用户类型,都不允许操作
+ if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
{
- _fusionCache = fusionCache;
- _userInfo = userInfo;
- _localizer = localizer;
- _trialRepository = trialRepository;
-
- if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
- if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
- if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
+ //---对不起,您的账户没有操作权限。
+ context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
+ return;
}
- //优先选择异步的方法
- public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
+ #endregion
+
+
+
+ //TrialId 传递的途径多种,可能在path 可能在body 可能在数组中,也可能在对象中,可能就在url
+ var trialIdStr = string.Empty;
+
+ if (!string.IsNullOrWhiteSpace(context.HttpContext.Request.Query["trialId"]))
{
- // var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault();
- //var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
+ trialIdStr = context.HttpContext.Request.Query["trialId"];
+ }
- #region 处理新的用户类型,不能操作项目相关接口
+ //先尝试从path中取TrialId
+ else if (context.RouteData.Values.Keys.Any(t => t.Contains("trialId")))
+ {
+ var index = context.RouteData.Values.Keys.ToList().IndexOf("trialId");
+ trialIdStr = context.RouteData.Values.Values.ToList()[index] as string;
+ }
+ else if (context.HttpContext.Request.Headers["Referer"].ToString().Contains("trialId"))
+ {
+ var headerStr = context.HttpContext.Request.Headers["Referer"].ToString();
- // 后期列举出具体的类型,其他任何用户类型,都不允许操作
- if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
+ var trialIdIndex = headerStr.IndexOf("trialId");
+
+
+ var matchResult = Regex.Match(headerStr.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
+
+ if (matchResult.Success)
{
- //---对不起,您的账户没有操作权限。
- context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
-
- return;
+ trialIdStr = matchResult.Value;
+ }
+ else
+ {
+ //---正则取请求Refer 中trialId 失败,请联系开发人员核查
+ context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
}
- #endregion
+ }
+ else
+ {
+ #region body 中取数据
+ //设置可以多次读
+ context.HttpContext.Request.EnableBuffering();
+ var reader = new StreamReader(context.HttpContext.Request.Body);
+ var contentFromBody = await reader.ReadToEndAsync();
+ //读取后,流的位置还原
+ context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
+ //context.HttpContext.Request.Body.Position = 0;
+ //找到参数位置在字符串中的索引
+ var trialIdIndex = contentFromBody.IndexOf("\"TrialId\"", StringComparison.OrdinalIgnoreCase);
- //TrialId 传递的途径多种,可能在path 可能在body 可能在数组中,也可能在对象中,可能就在url
- var trialIdStr = string.Empty;
-
- if (!string.IsNullOrWhiteSpace(context.HttpContext.Request.Query["trialId"]))
+ if (trialIdIndex > -1)
{
- trialIdStr = context.HttpContext.Request.Query["trialId"];
- }
+ // (?<="trialId" *: *").*?(?=",)
- //先尝试从path中取TrialId
- else if (context.RouteData.Values.Keys.Any(t => t.Contains("trialId")))
- {
- var index = context.RouteData.Values.Keys.ToList().IndexOf("trialId");
- trialIdStr = context.RouteData.Values.Values.ToList()[index] as string;
- }
- else if (context.HttpContext.Request.Headers["Referer"].ToString().Contains("trialId"))
- {
- var headerStr = context.HttpContext.Request.Headers["Referer"].ToString();
+ //使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}
- var trialIdIndex = headerStr.IndexOf("trialId");
-
-
- var matchResult = Regex.Match(headerStr.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
+ var matchResult = Regex.Match(contentFromBody.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
if (matchResult.Success)
{
+ //有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
+
trialIdStr = matchResult.Value;
+
+ var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
+
+ if (string.IsNullOrWhiteSpace(trialStatusStr))
+ {
+ //数据库 检查该项目Id不对
+ context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
+ }
}
else
{
@@ -89,93 +133,48 @@ namespace IRaCIS.Core.Application.Filter
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
}
- }
- else
- {
- #region body 中取数据
-
- //设置可以多次读
- context.HttpContext.Request.EnableBuffering();
- var reader = new StreamReader(context.HttpContext.Request.Body);
- var contentFromBody = await reader.ReadToEndAsync();
- //读取后,流的位置还原
- context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
- //context.HttpContext.Request.Body.Position = 0;
-
- //找到参数位置在字符串中的索引
- var trialIdIndex = contentFromBody.IndexOf("\"TrialId\"", StringComparison.OrdinalIgnoreCase);
-
- if (trialIdIndex > -1)
- {
- // (?<="trialId" *: *").*?(?=",)
-
- //使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}
-
- var matchResult = Regex.Match(contentFromBody.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
-
- if (matchResult.Success)
- {
- //有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
-
- trialIdStr = matchResult.Value;
-
- var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
-
- if (string.IsNullOrWhiteSpace(trialStatusStr))
- {
- //数据库 检查该项目Id不对
- context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
- }
- }
- else
- {
- //---正则取请求Refer 中trialId 失败,请联系开发人员核查
- context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
- }
-
- //使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
- //trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
- }
-
- #endregion
+ //使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
+ //trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
}
- //通过path 或者body 找到trialId 了
- if (!string.IsNullOrWhiteSpace(trialIdStr))
+ #endregion
+ }
+
+ //通过path 或者body 找到trialId 了
+ if (!string.IsNullOrWhiteSpace(trialIdStr))
+ {
+ var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
+
+ // 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
+ if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
{
- var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
- // 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
- if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
- {
-
- await next.Invoke();
-
- }
- // 项目停止、或者完成 不允许操作
- else
- {
- //---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
- context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
-
- }
-
- }
- //添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
- else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId))
- {
await next.Invoke();
- }
+ }
+ // 项目停止、或者完成 不允许操作
else
{
- //如果项目相关接口没有传递trialId 会来到这里,提醒,以便修改
+ //---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
+ context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
- //---该接口参数中,没有传递项目编号,请核对。
- context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_MissingProjectNumber"]));
}
-
}
+ //添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
+ else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId))
+ {
+ await next.Invoke();
+ }
+
+ else
+ {
+ //如果项目相关接口没有传递trialId 会来到这里,提醒,以便修改
+
+ //---该接口参数中,没有传递项目编号,请核对。
+ context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_MissingProjectNumber"]));
+ }
+
+
}
}
diff --git a/IRaCIS.Core.Application/BusinessFilter/UnifiedApiResultFilter.cs b/IRaCIS.Core.Application/BusinessFilter/UnifiedApiResultFilter.cs
index daf59c30f..b8a4977f8 100644
--- a/IRaCIS.Core.Application/BusinessFilter/UnifiedApiResultFilter.cs
+++ b/IRaCIS.Core.Application/BusinessFilter/UnifiedApiResultFilter.cs
@@ -3,121 +3,120 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
-namespace IRaCIS.Core.Application.Service.BusinessFilter
+namespace IRaCIS.Core.Application.Service.BusinessFilter;
+
+///
+/// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
+/// by zhouhang 2021.09.12 周末
+///
+public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
{
- ///
- /// 统一返回前端数据包装,之前在控制器包装,现在修改为动态Api 在ResultFilter这里包装,减少重复冗余代码
- /// by zhouhang 2021.09.12 周末
- ///
- public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
+ private readonly ILogger _logger;
+
+ public UnifiedApiResultFilter(ILogger logger)
{
- private readonly ILogger _logger;
+ _logger = logger;
+ }
- public UnifiedApiResultFilter(ILogger logger)
+ ///
+ /// 异步版本
+ ///
+ ///
+ ///
+ ///
+ public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
+ {
+
+ if (context.Result is ObjectResult objectResult)
{
- _logger = logger;
- }
+ var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
- ///
- /// 异步版本
- ///
- ///
- ///
- ///
- public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
- {
-
- if (context.Result is ObjectResult objectResult)
+ //是200 并且没有包装 那么包装结果
+ if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
{
- var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
- //是200 并且没有包装 那么包装结果
- if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
+ var type = objectResult.Value?.GetType();
+
+
+ if (type != null && type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(ValueTuple<,>) || type.GetGenericTypeDefinition() == typeof(Tuple<,>)))
{
- var type = objectResult.Value?.GetType();
-
-
- if (type != null && type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(ValueTuple<,>) || type.GetGenericTypeDefinition() == typeof(Tuple<,>)))
- {
-
- //报错
- //var tuple = (object, object))objectResult.Value;
- //var (val1, val2) = ((dynamic, dynamic))objectResult.Value;
- //var apiResponse = ResponseOutput.Ok(val1, val2);
-
- //OK
- var tuple = (dynamic)objectResult.Value;
- var apiResponse = ResponseOutput.Ok(tuple!.Item1, tuple!.Item2);
-
-
- objectResult.Value = apiResponse;
- objectResult.DeclaredType = apiResponse.GetType();
- }
- else
- {
- var apiResponse = ResponseOutput.Ok(objectResult.Value);
-
- objectResult.Value = apiResponse;
- objectResult.DeclaredType = apiResponse.GetType();
- }
+ //报错
+ //var tuple = (object, object))objectResult.Value;
+ //var (val1, val2) = ((dynamic, dynamic))objectResult.Value;
+ //var apiResponse = ResponseOutput.Ok(val1, val2);
+
+ //OK
+ var tuple = (dynamic)objectResult.Value;
+ var apiResponse = ResponseOutput.Ok(tuple!.Item1, tuple!.Item2);
+ objectResult.Value = apiResponse;
+ objectResult.DeclaredType = apiResponse.GetType();
}
- //如果是200 是IResponseOutput 记录下日志
- else if (statusCode == 200 && (objectResult.Value is IResponseOutput))
+ else
{
- var result = objectResult.Value as IResponseOutput;
-
- if (!string.IsNullOrWhiteSpace(result.LocalizedInfo))
- {
- //统一在这里记录国际化的日志信息
- _logger.LogWarning($"{result.LocalizedInfo}");
- }
-
- }
-
- else if (statusCode != 200 && !(objectResult.Value is IResponseOutput))
- {
- //---程序错误,请联系开发人员。
- var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
+ var apiResponse = ResponseOutput.Ok(objectResult.Value);
objectResult.Value = apiResponse;
objectResult.DeclaredType = apiResponse.GetType();
}
+
}
-
- await next.Invoke();
-
- }
-
- public static bool IsTupleType(Type type, bool checkBaseTypes = false)
- {
- if (type == null)
- throw new ArgumentNullException(nameof(type));
-
- if (type == typeof(Tuple))
- return true;
-
- while (type != null)
+ //如果是200 是IResponseOutput 记录下日志
+ else if (statusCode == 200 && (objectResult.Value is IResponseOutput))
{
- if (type.IsGenericType)
+ var result = objectResult.Value as IResponseOutput;
+
+ if (!string.IsNullOrWhiteSpace(result.LocalizedInfo))
{
- var genType = type.GetGenericTypeDefinition();
- if (genType == typeof(Tuple<>)
- || genType == typeof(Tuple<,>)
- || genType == typeof(Tuple<,>))
- return true;
+ //统一在这里记录国际化的日志信息
+ _logger.LogWarning($"{result.LocalizedInfo}");
}
- if (!checkBaseTypes)
- break;
-
- type = type.BaseType;
}
- return false;
+ else if (statusCode != 200 && !(objectResult.Value is IResponseOutput))
+ {
+ //---程序错误,请联系开发人员。
+ var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
+
+ objectResult.Value = apiResponse;
+ objectResult.DeclaredType = apiResponse.GetType();
+ }
+
}
+
+ await next.Invoke();
+
+ }
+
+ public static bool IsTupleType(Type type, bool checkBaseTypes = false)
+ {
+ if (type == null)
+ throw new ArgumentNullException(nameof(type));
+
+ if (type == typeof(Tuple))
+ return true;
+
+ while (type != null)
+ {
+ if (type.IsGenericType)
+ {
+ var genType = type.GetGenericTypeDefinition();
+ if (genType == typeof(Tuple<>)
+ || genType == typeof(Tuple<,>)
+ || genType == typeof(Tuple<,>))
+ return true;
+ }
+
+ if (!checkBaseTypes)
+ break;
+
+ type = type.BaseType;
+ }
+
+ return false;
}
}
diff --git a/IRaCIS.Core.Application/GlobalUsings.cs b/IRaCIS.Core.Application/GlobalUsings.cs
index 1183f17bd..6798764ad 100644
--- a/IRaCIS.Core.Application/GlobalUsings.cs
+++ b/IRaCIS.Core.Application/GlobalUsings.cs
@@ -1,5 +1,4 @@
global using AutoMapper.QueryableExtensions;
-global using IRaCIS.Core.Application;
global using IRaCIS.Core.Application.Service;
global using IRaCIS.Core.Domain.Models;
global using IRaCIS.Core.Infra.EFCore;
diff --git a/IRaCIS.Core.Application/Helper/CacheHelper.cs b/IRaCIS.Core.Application/Helper/CacheHelper.cs
index 33d9cb9cd..c1cf93748 100644
--- a/IRaCIS.Core.Application/Helper/CacheHelper.cs
+++ b/IRaCIS.Core.Application/Helper/CacheHelper.cs
@@ -1,70 +1,69 @@
-namespace IRaCIS.Core.Application.Helper
+namespace IRaCIS.Core.Application.Helper;
+
+
+public static class CacheKeys
{
+ //项目缓存
+ public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
- public static class CacheKeys
+ //检查编号递增锁
+ public static string TrialStudyMaxCode(Guid trialId) => $"TrialStudyMaxCode:{trialId}";
+
+ public static string TrialStudyUidUploading(Guid trialId, string studyUid) => $"TrialStudyUid:{trialId}_{studyUid}";
+ //CRC上传影像提交锁key
+ public static string TrialStudyUidDBLock(Guid trialId, string studyUid) => $"TrialStudyUidDBLock:{trialId}_{studyUid}";
+
+ public static string TrialTaskStudyUidUploading(Guid trialId, Guid visiTaskId, string studyUid) => $"TrialStudyUid:{trialId}_{visiTaskId}_{studyUid}";
+ //影像后处理上传提交锁key
+ public static string TrialTaskStudyUidDBLock(Guid trialId, Guid visiTaskId, string studyUid) => $"TrialTaskStudyUidDBLock:{trialId}_{visiTaskId}_{studyUid}";
+ //系统匿名化
+ public static string SystemAnonymization => $"SystemAnonymization";
+ //前端国际化
+ public static string FrontInternational => $"FrontInternationalList";
+
+ //登录挤账号
+ public static string UserToken(Guid userId) => $"UserToken:{userId}";
+
+ //超时没请求接口自动退出
+ public static string UserAutoLoginOut(Guid userId) => $"UserAutoLoginOut:{userId}";
+
+ ///
+ /// 跳过阅片
+ ///
+ ///
+ ///
+ public static string SkipReadingCacheKey(Guid userId) => $"{userId}SkipReadingCache";
+
+
+ ///
+ /// 开始阅片时间
+ ///
+ ///
+ ///
+ public static string StartReadingTimeKey(Guid userId) => $"{userId}StartReadingTime";
+
+ ///
+ /// 开始休息时间
+ ///
+ ///
+ ///
+ public static string StartRestTime(Guid userId) => $"{userId}StartRestTime";
+
+}
+
+public static class CacheHelper
+{
+ public static async Task GetTrialStatusAsync(Guid trialId, IRepository _trialRepository)
{
- //项目缓存
- public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
-
- //检查编号递增锁
- public static string TrialStudyMaxCode(Guid trialId) => $"TrialStudyMaxCode:{trialId}";
-
- public static string TrialStudyUidUploading(Guid trialId, string studyUid) => $"TrialStudyUid:{trialId}_{studyUid}";
- //CRC上传影像提交锁key
- public static string TrialStudyUidDBLock(Guid trialId, string studyUid) => $"TrialStudyUidDBLock:{trialId}_{studyUid}";
-
- public static string TrialTaskStudyUidUploading(Guid trialId, Guid visiTaskId, string studyUid) => $"TrialStudyUid:{trialId}_{visiTaskId}_{studyUid}";
- //影像后处理上传提交锁key
- public static string TrialTaskStudyUidDBLock(Guid trialId, Guid visiTaskId, string studyUid) => $"TrialTaskStudyUidDBLock:{trialId}_{visiTaskId}_{studyUid}";
- //系统匿名化
- public static string SystemAnonymization => $"SystemAnonymization";
- //前端国际化
- public static string FrontInternational => $"FrontInternationalList";
-
- //登录挤账号
- public static string UserToken(Guid userId) => $"UserToken:{userId}";
-
- //超时没请求接口自动退出
- public static string UserAutoLoginOut(Guid userId) => $"UserAutoLoginOut:{userId}";
-
- ///
- /// 跳过阅片
- ///
- ///
- ///
- public static string SkipReadingCacheKey(Guid userId) => $"{userId}SkipReadingCache";
-
-
- ///
- /// 开始阅片时间
- ///
- ///
- ///
- public static string StartReadingTimeKey(Guid userId) => $"{userId}StartReadingTime";
-
- ///
- /// 开始休息时间
- ///
- ///
- ///
- public static string StartRestTime(Guid userId) => $"{userId}StartRestTime";
+ var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync();
+ return statusStr;
}
- public static class CacheHelper
+ public static async Task> GetSystemAnonymizationListAsync(IRepository _systemAnonymizationRepository)
{
- public static async Task GetTrialStatusAsync(Guid trialId, IRepository _trialRepository)
- {
- var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync();
+ var list = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
- return statusStr;
- }
-
- public static async Task> GetSystemAnonymizationListAsync(IRepository _systemAnonymizationRepository)
- {
- var list = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
-
- return list;
- }
+ return list;
}
}
diff --git a/IRaCIS.Core.Application/Helper/FileConvertHelper.cs b/IRaCIS.Core.Application/Helper/FileConvertHelper.cs
index 51c3a5f65..5b34f64f3 100644
--- a/IRaCIS.Core.Application/Helper/FileConvertHelper.cs
+++ b/IRaCIS.Core.Application/Helper/FileConvertHelper.cs
@@ -1,34 +1,33 @@
using System.Diagnostics;
-namespace IRaCIS.Core.Application.Helper
+namespace IRaCIS.Core.Application.Helper;
+
+public class FileConvertHelper
{
- public class FileConvertHelper
+
+
+ static public void ConvertWordToPdf(string inputWordFilePath, string outputPdfDir)
{
+ // 设置 libreoffice 命令行参数
+ string arguments = $"--headless --invisible --convert-to pdf \"{inputWordFilePath}\" --outdir \"{outputPdfDir}\"";
-
- static public void ConvertWordToPdf(string inputWordFilePath, string outputPdfDir)
+ // 启动 libreoffice 进程
+ using (Process process = new Process())
{
- // 设置 libreoffice 命令行参数
- string arguments = $"--headless --invisible --convert-to pdf \"{inputWordFilePath}\" --outdir \"{outputPdfDir}\"";
+ process.StartInfo.FileName = "libreoffice";
+ process.StartInfo.Arguments = arguments;
+ process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
+ process.StartInfo.RedirectStandardOutput = true;
+ process.StartInfo.RedirectStandardError = true;
+ process.StartInfo.UseShellExecute = false;
+ process.StartInfo.CreateNoWindow = true;
- // 启动 libreoffice 进程
- using (Process process = new Process())
- {
- process.StartInfo.FileName = "libreoffice";
- process.StartInfo.Arguments = arguments;
- process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
- process.StartInfo.RedirectStandardOutput = true;
- process.StartInfo.RedirectStandardError = true;
- process.StartInfo.UseShellExecute = false;
- process.StartInfo.CreateNoWindow = true;
+ process.Start();
- process.Start();
-
- // 等待进程结束
- process.WaitForExit();
- }
+ // 等待进程结束
+ process.WaitForExit();
}
-
-
}
+
+
}
diff --git a/IRaCIS.Core.Application/Helper/HolidayHelper.cs b/IRaCIS.Core.Application/Helper/HolidayHelper.cs
index cbd3be004..dede05206 100644
--- a/IRaCIS.Core.Application/Helper/HolidayHelper.cs
+++ b/IRaCIS.Core.Application/Helper/HolidayHelper.cs
@@ -1,106 +1,105 @@
using RestSharp;
-namespace IRaCIS.Core.Application.Helper
+namespace IRaCIS.Core.Application.Helper;
+
+
+#region 对接模型
+public class HolidayCalendar
{
-
- #region 对接模型
- public class HolidayCalendar
- {
- public string Name { get; set; }
- public string Version { get; set; }
- public string Generated { get; set; }
- public string Timezone { get; set; }
- public string Author { get; set; }
- public string URL { get; set; }
- public Dictionary> Years { get; set; }
- }
-
- public class HolidayYear
- {
- public string Name { get; set; }
- public DateTime StartDate { get; set; }
- public DateTime EndDate { get; set; }
- public int Duration { get; set; }
- public List CompDays { get; set; }
- public string URL { get; set; }
- public string Memo { get; set; }
- }
- #endregion
-
-
-
-
- public class HolidayHelper
- {
- ///
- /// github 链接:https://github.com/lanceliao/china-holiday-calender?tab=readme-ov-file
- /// 接口请求参考文档:https://www.koudingke.cn/docs/zh-Hans/net-lib-docs/latest/RestSharp/Usage/Usage
- ///
- private static RestClient _client => new RestClient("https://www.shuyz.com/githubfiles/china-holiday-calender/master/holidayAPI.json");
-
- private static HolidayCalendar _holidayCalendar { get; set; }
-
-
- private static List _holidays = new List();
- private static List _compensatedWorkdays = new List();
-
- static HolidayHelper()
- {
- _holidayCalendar = _client.Get(new RestRequest()) ?? new HolidayCalendar();
-
- foreach (var year in _holidayCalendar.Years.Values.SelectMany(x => x))
- {
- // 添加节假日到假日集合
- for (DateTime date = year.StartDate; date <= year.EndDate; date = date.AddDays(1))
- {
- _holidays.Add(date);
- }
-
- // 添加补班日到补班日集合
- foreach (var compDay in year.CompDays)
- {
- _compensatedWorkdays.Add(compDay);
- }
- }
-
- }
-
- public static TimeSpan GetChinaWorkTimeSpan(DateTime startDate, DateTime endDate)
- {
- if (startDate > endDate)
- {
- throw new ArgumentException("结束日期必须大于或等于开始日期");
- }
-
- var diffTimeSpan = endDate - startDate;
-
- // 初始化工作日数为0
- int workdays = 0;
-
- // 找出在给定日期范围内的假期和补班日
- var filteredHolidays = _holidays.Where(d => d >= startDate && d <= endDate).ToList();
- var filteredCompensatedWorkdays = _compensatedWorkdays.Where(d => d >= startDate && d <= endDate).ToList();
-
- // 遍历日期范围,计算工作日 注意 这里是小于
- for (DateTime date = startDate.Date; date < endDate.Date; date = date.AddDays(1))
- {
- // 判断是否为工作日
- bool isWeekend = date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
- bool isHoliday = filteredHolidays.Contains(date);
- bool isCompensatedWorkday = filteredCompensatedWorkdays.Contains(date);
-
- // 如果是补班日,或是平日(非假期,非周末),则算作工作日
- if (isCompensatedWorkday || (!isWeekend && !isHoliday))
- {
- workdays++;
- }
- }
-
- return new TimeSpan(workdays, diffTimeSpan.Hours, diffTimeSpan.Minutes, diffTimeSpan.Seconds);
-
-
- }
-
-
- }
+ public string Name { get; set; }
+ public string Version { get; set; }
+ public string Generated { get; set; }
+ public string Timezone { get; set; }
+ public string Author { get; set; }
+ public string URL { get; set; }
+ public Dictionary> Years { get; set; }
+}
+
+public class HolidayYear
+{
+ public string Name { get; set; }
+ public DateTime StartDate { get; set; }
+ public DateTime EndDate { get; set; }
+ public int Duration { get; set; }
+ public List CompDays { get; set; }
+ public string URL { get; set; }
+ public string Memo { get; set; }
+}
+#endregion
+
+
+
+
+public class HolidayHelper
+{
+ ///
+ /// github 链接:https://github.com/lanceliao/china-holiday-calender?tab=readme-ov-file
+ /// 接口请求参考文档:https://www.koudingke.cn/docs/zh-Hans/net-lib-docs/latest/RestSharp/Usage/Usage
+ ///
+ private static RestClient _client => new RestClient("https://www.shuyz.com/githubfiles/china-holiday-calender/master/holidayAPI.json");
+
+ private static HolidayCalendar _holidayCalendar { get; set; }
+
+
+ private static List _holidays = new List();
+ private static List _compensatedWorkdays = new List();
+
+ static HolidayHelper()
+ {
+ _holidayCalendar = _client.Get(new RestRequest()) ?? new HolidayCalendar();
+
+ foreach (var year in _holidayCalendar.Years.Values.SelectMany(x => x))
+ {
+ // 添加节假日到假日集合
+ for (DateTime date = year.StartDate; date <= year.EndDate; date = date.AddDays(1))
+ {
+ _holidays.Add(date);
+ }
+
+ // 添加补班日到补班日集合
+ foreach (var compDay in year.CompDays)
+ {
+ _compensatedWorkdays.Add(compDay);
+ }
+ }
+
+ }
+
+ public static TimeSpan GetChinaWorkTimeSpan(DateTime startDate, DateTime endDate)
+ {
+ if (startDate > endDate)
+ {
+ throw new ArgumentException("结束日期必须大于或等于开始日期");
+ }
+
+ var diffTimeSpan = endDate - startDate;
+
+ // 初始化工作日数为0
+ int workdays = 0;
+
+ // 找出在给定日期范围内的假期和补班日
+ var filteredHolidays = _holidays.Where(d => d >= startDate && d <= endDate).ToList();
+ var filteredCompensatedWorkdays = _compensatedWorkdays.Where(d => d >= startDate && d <= endDate).ToList();
+
+ // 遍历日期范围,计算工作日 注意 这里是小于
+ for (DateTime date = startDate.Date; date < endDate.Date; date = date.AddDays(1))
+ {
+ // 判断是否为工作日
+ bool isWeekend = date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
+ bool isHoliday = filteredHolidays.Contains(date);
+ bool isCompensatedWorkday = filteredCompensatedWorkdays.Contains(date);
+
+ // 如果是补班日,或是平日(非假期,非周末),则算作工作日
+ if (isCompensatedWorkday || (!isWeekend && !isHoliday))
+ {
+ workdays++;
+ }
+ }
+
+ return new TimeSpan(workdays, diffTimeSpan.Hours, diffTimeSpan.Minutes, diffTimeSpan.Seconds);
+
+
+ }
+
+
}
diff --git a/IRaCIS.Core.Application/Helper/IRCEmailPasswordHelper.cs b/IRaCIS.Core.Application/Helper/IRCEmailPasswordHelper.cs
index a2c23c1bd..efb9ad4e2 100644
--- a/IRaCIS.Core.Application/Helper/IRCEmailPasswordHelper.cs
+++ b/IRaCIS.Core.Application/Helper/IRCEmailPasswordHelper.cs
@@ -1,78 +1,77 @@
-namespace IRaCIS.Core.Application.Helper
+namespace IRaCIS.Core.Application.Helper;
+
+public static class IRCEmailPasswordHelper
{
- public static class IRCEmailPasswordHelper
+ private static readonly Random Random = new Random();
+
+ //显示位数:3分之2的位数,向上取整
+ //取哪几个个值:最后一位和前面几位
+ //其他:3个***。
+ //比如:hlj23@126.com
+ //为:hlj***3@126.com
+
+ //he@126.com
+ //为:h*** e@126.com
+
+ public static string MaskEmail(string email)
{
- private static readonly Random Random = new Random();
- //显示位数:3分之2的位数,向上取整
- //取哪几个个值:最后一位和前面几位
- //其他:3个***。
- //比如:hlj23@126.com
- //为:hlj***3@126.com
+ // 找到 "@" 符号的位置
+ int atIndex = email.IndexOf('@');
- //he@126.com
- //为:h*** e@126.com
+ string visiblePartBefore = email.Substring(0, atIndex);
- public static string MaskEmail(string email)
+ string afterAt = email.Substring(atIndex + 1);
+
+ int visibleLength = (int)Math.Ceiling((double)visiblePartBefore.Length * 2 / 3);
+
+ // 替换中间两位字符为星号
+ string hiddenPartBeforeAt = visiblePartBefore.Substring(0, visibleLength - 1) + "***" + visiblePartBefore.Last();
+
+
+ // 组合隐藏和可见部分
+ string hiddenEmail = hiddenPartBeforeAt + "@" + afterAt;
+
+ return hiddenEmail;
+ }
+
+ ///
+ /// 密码必须包含:1)8 – 32 个字符;2)至少1个数字;3) 至少1个大写字母;4)至少1个小写字母;5)至少1个特殊字符 (~!-@#$%^&*_+?)
+ ///
+ ///
+ public static string GenerateRandomPassword(int length)
+ {
+ // 必须包含的字符组
+ const string numbers = "0123456789";
+ const string upperCaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ const string lowerCaseLetters = "abcdefghijklmnopqrstuvwxyz";
+ const string specialCharacters = "~!-@#$%^&*_+?";
+
+ // 随机选择至少一个字符
+ char[] requiredCharacters =
{
+ numbers[Random.Next(numbers.Length)],
+ upperCaseLetters[Random.Next(upperCaseLetters.Length)],
+ lowerCaseLetters[Random.Next(lowerCaseLetters.Length)],
+ specialCharacters[Random.Next(specialCharacters.Length)]
+ };
- // 找到 "@" 符号的位置
- int atIndex = email.IndexOf('@');
+ // 构建剩余的字符集,用于填充密码的其余部分
+ string allCharacters = numbers + upperCaseLetters + lowerCaseLetters + specialCharacters;
- string visiblePartBefore = email.Substring(0, atIndex);
+ // 确保密码长度满足用户要求
+ char[] password = new char[length];
- string afterAt = email.Substring(atIndex + 1);
+ // 将必须包含的字符放入密码中
+ requiredCharacters.CopyTo(password, 0);
- int visibleLength = (int)Math.Ceiling((double)visiblePartBefore.Length * 2 / 3);
-
- // 替换中间两位字符为星号
- string hiddenPartBeforeAt = visiblePartBefore.Substring(0, visibleLength - 1) + "***" + visiblePartBefore.Last();
-
-
- // 组合隐藏和可见部分
- string hiddenEmail = hiddenPartBeforeAt + "@" + afterAt;
-
- return hiddenEmail;
+ // 填充剩余的字符
+ for (int i = requiredCharacters.Length; i < length; i++)
+ {
+ password[i] = allCharacters[Random.Next(allCharacters.Length)];
}
- ///
- /// 密码必须包含:1)8 – 32 个字符;2)至少1个数字;3) 至少1个大写字母;4)至少1个小写字母;5)至少1个特殊字符 (~!-@#$%^&*_+?)
- ///
- ///
- public static string GenerateRandomPassword(int length)
- {
- // 必须包含的字符组
- const string numbers = "0123456789";
- const string upperCaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- const string lowerCaseLetters = "abcdefghijklmnopqrstuvwxyz";
- const string specialCharacters = "~!-@#$%^&*_+?";
-
- // 随机选择至少一个字符
- char[] requiredCharacters =
- {
- numbers[Random.Next(numbers.Length)],
- upperCaseLetters[Random.Next(upperCaseLetters.Length)],
- lowerCaseLetters[Random.Next(lowerCaseLetters.Length)],
- specialCharacters[Random.Next(specialCharacters.Length)]
- };
-
- // 构建剩余的字符集,用于填充密码的其余部分
- string allCharacters = numbers + upperCaseLetters + lowerCaseLetters + specialCharacters;
-
- // 确保密码长度满足用户要求
- char[] password = new char[length];
-
- // 将必须包含的字符放入密码中
- requiredCharacters.CopyTo(password, 0);
-
- // 填充剩余的字符
- for (int i = requiredCharacters.Length; i < length; i++)
- {
- password[i] = allCharacters[Random.Next(allCharacters.Length)];
- }
-
- // 随机打乱密码字符顺序
- return new string(password.OrderBy(_ => Random.Next()).ToArray());
- }
+ // 随机打乱密码字符顺序
+ return new string(password.OrderBy(_ => Random.Next()).ToArray());
}
}
diff --git a/IRaCIS.Core.Application/Helper/InternationalizationHelper.cs b/IRaCIS.Core.Application/Helper/InternationalizationHelper.cs
index 390210a11..a1b47c837 100644
--- a/IRaCIS.Core.Application/Helper/InternationalizationHelper.cs
+++ b/IRaCIS.Core.Application/Helper/InternationalizationHelper.cs
@@ -5,204 +5,203 @@ using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
-namespace IRaCIS.Core.Application.Helper
+namespace IRaCIS.Core.Application.Helper;
+
+public static class InternationalizationHelper
{
- public static class InternationalizationHelper
+ public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources);
+
+ public static FileSystemWatcher FileSystemWatcher_US { get; set; }
+ public static FileSystemWatcher FileSystemWatcher_CN { get; set; }
+
+ private static void VerifyFolder()
{
- public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources);
-
- public static FileSystemWatcher FileSystemWatcher_US { get; set; }
- public static FileSystemWatcher FileSystemWatcher_CN { get; set; }
-
- private static void VerifyFolder()
+ if (!Directory.Exists(JsonFileFolder) ||
+ !Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase)))
{
- if (!Directory.Exists(JsonFileFolder) ||
- !Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase)))
- {
- throw new BusinessValidationFailedException("国际化Json文件目录有误");
- }
+ throw new BusinessValidationFailedException("国际化Json文件目录有误");
}
+ }
- public static async Task BatchAddJsonKeyValueAsync(List batchAddDtos)
+ public static async Task BatchAddJsonKeyValueAsync(List batchAddDtos)
+ {
+ VerifyFolder();
+
+ var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
+ var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
+
+
+ //更新json 文件 同时更新内存缓存的数据
+ foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
{
- VerifyFolder();
+ var json = await File.ReadAllTextAsync(filePath);
- var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
- var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
+ JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
+ // 添加或更新指定的键值对
- //更新json 文件 同时更新内存缓存的数据
- foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
+ if (filePath.Contains(StaticData.En_US_Json))
{
- var json = await File.ReadAllTextAsync(filePath);
-
- JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
-
- // 添加或更新指定的键值对
-
- if (filePath.Contains(StaticData.En_US_Json))
+ foreach (var item in batchAddDtos)
{
- foreach (var item in batchAddDtos)
- {
- jsonObject[item.Code] = item.Value;
+ jsonObject[item.Code] = item.Value;
- StaticData.En_US_Dic[item.Code] = item.Value;
-
- //日志记录该信息方便自己人看, 返回给客户的是配置的
- StaticData.Log_Locoalize_Dic[item.Code] = item.Description;
- }
- }
- else
- {
- foreach (var item in batchAddDtos)
- {
- jsonObject[item.Code] = item.Value;
-
- StaticData.Zh_CN_Dic[item.Code] = item.Value;
- }
- }
-
-
- await File.WriteAllTextAsync(filePath, jsonObject.ToString());
-
- }
- }
-
- public static async Task AddOrUpdateJsonKeyValueAsync(string key, string value, string valueCN, string description)
- {
-
- VerifyFolder();
-
- var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
- var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
-
-
- //更新json 文件 同时更新内存缓存的数据
- foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
- {
- var json = await File.ReadAllTextAsync(filePath);
-
- JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
-
- // 添加或更新指定的键值对
-
- if (filePath.Contains(StaticData.En_US_Json))
- {
- jsonObject[key] = value;
-
- StaticData.En_US_Dic[key] = value;
+ StaticData.En_US_Dic[item.Code] = item.Value;
//日志记录该信息方便自己人看, 返回给客户的是配置的
- StaticData.Log_Locoalize_Dic[key] = description;
+ StaticData.Log_Locoalize_Dic[item.Code] = item.Description;
}
- else
+ }
+ else
+ {
+ foreach (var item in batchAddDtos)
{
- jsonObject[key] = valueCN;
+ jsonObject[item.Code] = item.Value;
- StaticData.Zh_CN_Dic[key] = valueCN;
+ StaticData.Zh_CN_Dic[item.Code] = item.Value;
}
-
-
- await File.WriteAllTextAsync(filePath, jsonObject.ToString());
-
}
+
+ await File.WriteAllTextAsync(filePath, jsonObject.ToString());
+
}
+ }
+
+ public static async Task AddOrUpdateJsonKeyValueAsync(string key, string value, string valueCN, string description)
+ {
+
+ VerifyFolder();
+
+ var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
+ var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
- public static async Task InitInternationlizationDataAndWatchJsonFileAsync(IRepository _internationalizationRepository)
+ //更新json 文件 同时更新内存缓存的数据
+ foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
{
- //查询数据库的数据
- var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
+ var json = await File.ReadAllTextAsync(filePath);
+
+ JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
+
+ // 添加或更新指定的键值对
+
+ if (filePath.Contains(StaticData.En_US_Json))
{
- t.Code,
- t.Value,
- t.ValueCN,
- t.Description
- }).ToListAsync();
+ jsonObject[key] = value;
- //组织成json 文件
-
- var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
- var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
-
-
- //本地静态文件国际化需要
- foreach (var tojsonItem in toJsonList)
- {
- StaticData.En_US_Dic[tojsonItem.Code] = tojsonItem.Value;
- StaticData.Zh_CN_Dic[tojsonItem.Code] = tojsonItem.ValueCN;
+ StaticData.En_US_Dic[key] = value;
//日志记录该信息方便自己人看, 返回给客户的是配置的
- StaticData.Log_Locoalize_Dic[tojsonItem.Code] = tojsonItem.Description;
+ StaticData.Log_Locoalize_Dic[key] = description;
}
-
- File.WriteAllText(usJsonPath, JsonConvert.SerializeObject(StaticData.En_US_Dic));
- File.WriteAllText(cnJsonPath, JsonConvert.SerializeObject(StaticData.Zh_CN_Dic));
-
-
- //监测Json文件变更 实时刷新数据
-
- if (!File.Exists(usJsonPath) || !File.Exists(cnJsonPath))
+ else
{
- throw new BusinessValidationFailedException(StaticData.International("IRaCISCHangfireJob_FileNotFound"));
+ jsonObject[key] = valueCN;
+
+ StaticData.Zh_CN_Dic[key] = valueCN;
}
- // //监测Json文件变更 实时刷新数据
-
-
- FileSystemWatcher_US = new FileSystemWatcher
- {
- Path = Path.GetDirectoryName(usJsonPath)!,
- NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
- Filter = Path.GetFileName(usJsonPath),
- EnableRaisingEvents = true,
-
- };
- // 添加文件更改事件的处理程序
- FileSystemWatcher_US.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.En_US_Json);
-
-
- FileSystemWatcher_CN = new FileSystemWatcher
- {
- Path = Path.GetDirectoryName(cnJsonPath)!,
- NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
- Filter = Path.GetFileName(cnJsonPath),
- EnableRaisingEvents = true,
-
- };
- FileSystemWatcher_CN.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.Zh_CN_Json);
+ await File.WriteAllTextAsync(filePath, jsonObject.ToString());
}
-
-
- private static void LoadJsonFile(string filePath)
- {
- Console.WriteLine("刷新json内存数据");
- IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath, false, false);
-
- IConfigurationRoot enConfiguration = builder.Build();
-
- foreach (IConfigurationSection section in enConfiguration.GetChildren())
- {
- if (filePath.Contains(StaticData.En_US_Json))
- {
- StaticData.En_US_Dic[section.Key] = section.Value;
-
- }
- else
- {
- StaticData.Zh_CN_Dic[section.Key] = section.Value;
- }
- }
- }
-
-
-
-
-
-
}
+
+
+ public static async Task InitInternationlizationDataAndWatchJsonFileAsync(IRepository _internationalizationRepository)
+ {
+ //查询数据库的数据
+ var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
+ {
+ t.Code,
+ t.Value,
+ t.ValueCN,
+ t.Description
+ }).ToListAsync();
+
+ //组织成json 文件
+
+ var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
+ var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
+
+
+ //本地静态文件国际化需要
+ foreach (var tojsonItem in toJsonList)
+ {
+ StaticData.En_US_Dic[tojsonItem.Code] = tojsonItem.Value;
+ StaticData.Zh_CN_Dic[tojsonItem.Code] = tojsonItem.ValueCN;
+
+ //日志记录该信息方便自己人看, 返回给客户的是配置的
+ StaticData.Log_Locoalize_Dic[tojsonItem.Code] = tojsonItem.Description;
+ }
+
+ File.WriteAllText(usJsonPath, JsonConvert.SerializeObject(StaticData.En_US_Dic));
+ File.WriteAllText(cnJsonPath, JsonConvert.SerializeObject(StaticData.Zh_CN_Dic));
+
+
+ //监测Json文件变更 实时刷新数据
+
+ if (!File.Exists(usJsonPath) || !File.Exists(cnJsonPath))
+ {
+ throw new BusinessValidationFailedException(StaticData.International("IRaCISCHangfireJob_FileNotFound"));
+ }
+
+
+ // //监测Json文件变更 实时刷新数据
+
+
+ FileSystemWatcher_US = new FileSystemWatcher
+ {
+ Path = Path.GetDirectoryName(usJsonPath)!,
+ NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
+ Filter = Path.GetFileName(usJsonPath),
+ EnableRaisingEvents = true,
+
+ };
+ // 添加文件更改事件的处理程序
+ FileSystemWatcher_US.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.En_US_Json);
+
+
+ FileSystemWatcher_CN = new FileSystemWatcher
+ {
+ Path = Path.GetDirectoryName(cnJsonPath)!,
+ NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
+ Filter = Path.GetFileName(cnJsonPath),
+ EnableRaisingEvents = true,
+
+ };
+ FileSystemWatcher_CN.Changed += (sender, e) => LoadJsonFile(StaticData.Folder.Resources + "\\" + StaticData.Zh_CN_Json);
+
+ }
+
+
+
+ private static void LoadJsonFile(string filePath)
+ {
+ Console.WriteLine("刷新json内存数据");
+ IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath, false, false);
+
+ IConfigurationRoot enConfiguration = builder.Build();
+
+ foreach (IConfigurationSection section in enConfiguration.GetChildren())
+ {
+ if (filePath.Contains(StaticData.En_US_Json))
+ {
+ StaticData.En_US_Dic[section.Key] = section.Value;
+
+ }
+ else
+ {
+ StaticData.Zh_CN_Dic[section.Key] = section.Value;
+ }
+ }
+ }
+
+
+
+
+
+
}
diff --git a/IRaCIS.Core.Application/Helper/OSSService.cs b/IRaCIS.Core.Application/Helper/OSSService.cs
index 1239cded2..eb441c9e3 100644
--- a/IRaCIS.Core.Application/Helper/OSSService.cs
+++ b/IRaCIS.Core.Application/Helper/OSSService.cs
@@ -15,268 +15,337 @@ using Minio.DataModel.Args;
using System.Reactive.Linq;
using System.Runtime.InteropServices;
-namespace IRaCIS.Core.Application.Helper
+namespace IRaCIS.Core.Application.Helper;
+
+#region 绑定和返回模型
+
+[LowerCamelCaseJson]
+public class MinIOOptions : AWSOptions
{
- #region 绑定和返回模型
+ public int Port { get; set; }
- [LowerCamelCaseJson]
- public class MinIOOptions : AWSOptions
+}
+
+
+public class AWSOptions
+{
+ public string EndPoint { get; set; }
+ public bool UseSSL { get; set; }
+ public string AccessKeyId { get; set; }
+ public string RoleArn { get; set; }
+ public string SecretAccessKey { get; set; }
+ public string BucketName { get; set; }
+ public string ViewEndpoint { get; set; }
+ public int DurationSeconds { get; set; }
+ public string Region { get; set; }
+}
+
+public class AliyunOSSOptions
+{
+ public string RegionId { get; set; }
+ public string AccessKeyId { get; set; }
+ public string AccessKeySecret { get; set; }
+
+ public string InternalEndpoint { get; set; }
+
+ public string EndPoint { get; set; }
+ public string BucketName { get; set; }
+
+ public string RoleArn { get; set; }
+
+ public string Region { get; set; }
+
+ public string ViewEndpoint { get; set; }
+
+ public int DurationSeconds { get; set; }
+
+
+
+}
+
+public class ObjectStoreServiceOptions
+{
+ public string ObjectStoreUse { get; set; }
+
+ public AliyunOSSOptions AliyunOSS { get; set; }
+
+
+ public MinIOOptions MinIO { get; set; }
+
+ public AWSOptions AWS { get; set; }
+
+}
+
+public class ObjectStoreDTO
+{
+ public string ObjectStoreUse { get; set; }
+
+
+ public AliyunOSSTempToken AliyunOSS { get; set; }
+
+ public MinIOOptions MinIO { get; set; }
+
+ public AWSTempToken AWS { get; set; }
+
+}
+
+[LowerCamelCaseJson]
+public class AliyunOSSTempToken
+{
+ public string AccessKeyId { get; set; }
+ public string AccessKeySecret { get; set; }
+
+ public string EndPoint { get; set; }
+ public string BucketName { get; set; }
+
+ public string Region { get; set; }
+
+ public string ViewEndpoint { get; set; }
+
+ public string SecurityToken { get; set; }
+ public DateTime Expiration { get; set; }
+
+
+}
+
+[LowerCamelCaseJson]
+public class AWSTempToken
+{
+ public string Region { get; set; }
+ public string SessionToken { get; set; }
+ public string EndPoint { get; set; }
+ public string AccessKeyId { get; set; }
+ public string SecretAccessKey { get; set; }
+ public string BucketName { get; set; }
+ public string ViewEndpoint { get; set; }
+ public DateTime Expiration { get; set; }
+}
+
+public enum ObjectStoreUse
+{
+ AliyunOSS = 0,
+ MinIO = 1,
+ AWS = 2,
+}
+
+#endregion
+
+// aws 参考链接 https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3/S3/S3_Basics
+
+public interface IOSSService
+{
+ public Task UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true);
+ public Task UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true);
+
+ public Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath);
+
+ public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; }
+
+ public Task GetSignedUrl(string ossRelativePath);
+
+ public Task DeleteFromPrefix(string prefix);
+
+ public Task GetObjectStoreTempToken();
+}
+
+
+public class OSSService : IOSSService
+{
+ public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; }
+
+ private AliyunOSSTempToken AliyunOSSTempToken { get; set; }
+
+ private AWSTempToken AWSTempToken { get; set; }
+
+
+ public OSSService(IOptionsMonitor options)
{
- public int Port { get; set; }
+ ObjectStoreServiceOptions = options.CurrentValue;
+ GetObjectStoreTempToken().GetAwaiter().GetResult();
}
-
- public class AWSOptions
+ ///
+ /// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true)
{
- public string EndPoint { get; set; }
- public bool UseSSL { get; set; }
- public string AccessKeyId { get; set; }
- public string RoleArn { get; set; }
- public string SecretAccessKey { get; set; }
- public string BucketName { get; set; }
- public string ViewEndpoint { get; set; }
- public int DurationSeconds { get; set; }
- public string Region { get; set; }
- }
+ var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{fileRealName}" : $"{oosFolderPath}/{fileRealName}";
- public class AliyunOSSOptions
- {
- public string RegionId { get; set; }
- public string AccessKeyId { get; set; }
- public string AccessKeySecret { get; set; }
-
- public string InternalEndpoint { get; set; }
-
- public string EndPoint { get; set; }
- public string BucketName { get; set; }
-
- public string RoleArn { get; set; }
-
- public string Region { get; set; }
-
- public string ViewEndpoint { get; set; }
-
- public int DurationSeconds { get; set; }
-
-
-
- }
-
- public class ObjectStoreServiceOptions
- {
- public string ObjectStoreUse { get; set; }
-
- public AliyunOSSOptions AliyunOSS { get; set; }
-
-
- public MinIOOptions MinIO { get; set; }
-
- public AWSOptions AWS { get; set; }
-
- }
-
- public class ObjectStoreDTO
- {
- public string ObjectStoreUse { get; set; }
-
-
- public AliyunOSSTempToken AliyunOSS { get; set; }
-
- public MinIOOptions MinIO { get; set; }
-
- public AWSTempToken AWS { get; set; }
-
- }
-
- [LowerCamelCaseJson]
- public class AliyunOSSTempToken
- {
- public string AccessKeyId { get; set; }
- public string AccessKeySecret { get; set; }
-
- public string EndPoint { get; set; }
- public string BucketName { get; set; }
-
- public string Region { get; set; }
-
- public string ViewEndpoint { get; set; }
-
- public string SecurityToken { get; set; }
- public DateTime Expiration { get; set; }
-
-
- }
-
- [LowerCamelCaseJson]
- public class AWSTempToken
- {
- public string Region { get; set; }
- public string SessionToken { get; set; }
- public string EndPoint { get; set; }
- public string AccessKeyId { get; set; }
- public string SecretAccessKey { get; set; }
- public string BucketName { get; set; }
- public string ViewEndpoint { get; set; }
- public DateTime Expiration { get; set; }
- }
-
- public enum ObjectStoreUse
- {
- AliyunOSS = 0,
- MinIO = 1,
- AWS = 2,
- }
-
- #endregion
-
- // aws 参考链接 https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3/S3/S3_Basics
-
- public interface IOSSService
- {
- public Task UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true);
- public Task UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true);
-
- public Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath);
-
- public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; }
-
- public Task GetSignedUrl(string ossRelativePath);
-
- public Task DeleteFromPrefix(string prefix);
-
- public Task GetObjectStoreTempToken();
- }
-
-
- public class OSSService : IOSSService
- {
- public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; }
-
- private AliyunOSSTempToken AliyunOSSTempToken { get; set; }
-
- private AWSTempToken AWSTempToken { get; set; }
-
-
- public OSSService(IOptionsMonitor options)
+ try
{
- ObjectStoreServiceOptions = options.CurrentValue;
-
- GetObjectStoreTempToken().GetAwaiter().GetResult();
- }
-
- ///
- /// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
- ///
- ///
- ///
- ///
- ///
- ///
- public async Task UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true)
- {
- var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{fileRealName}" : $"{oosFolderPath}/{fileRealName}";
-
- try
+ using (var memoryStream = new MemoryStream())
{
- using (var memoryStream = new MemoryStream())
+ fileStream.Seek(0, SeekOrigin.Begin);
+
+ fileStream.CopyTo(memoryStream);
+
+ memoryStream.Seek(0, SeekOrigin.Begin);
+
+
+ if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
{
- fileStream.Seek(0, SeekOrigin.Begin);
+ var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
- fileStream.CopyTo(memoryStream);
-
- memoryStream.Seek(0, SeekOrigin.Begin);
+ var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
- if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
+
+ // 上传文件
+ var result = _ossClient.PutObject(aliConfig.BucketName, ossRelativePath, memoryStream);
+
+ }
+ else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
+ {
+ var minIOConfig = ObjectStoreServiceOptions.MinIO;
+
+
+ var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
+ .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
+ .Build();
+
+ var putObjectArgs = new PutObjectArgs()
+ .WithBucket(minIOConfig.BucketName)
+ .WithObject(ossRelativePath)
+ .WithStreamData(memoryStream)
+ .WithObjectSize(memoryStream.Length);
+
+ await minioClient.PutObjectAsync(putObjectArgs);
+ }
+ else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
+ {
+ var awsConfig = ObjectStoreServiceOptions.AWS;
+
+ var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
+
+
+
+ //提供awsEndPoint(域名)进行访问配置
+ var clientConfig = new AmazonS3Config
{
- var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
+ RegionEndpoint = RegionEndpoint.USEast1,
+ UseHttp = true,
+ };
- var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
+ var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
-
-
- // 上传文件
- var result = _ossClient.PutObject(aliConfig.BucketName, ossRelativePath, memoryStream);
-
- }
- else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
+ var putObjectRequest = new Amazon.S3.Model.PutObjectRequest()
{
- var minIOConfig = ObjectStoreServiceOptions.MinIO;
+ BucketName = awsConfig.BucketName,
+ InputStream = memoryStream,
+ Key = ossRelativePath,
+ };
-
- var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
- .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
- .Build();
-
- var putObjectArgs = new PutObjectArgs()
- .WithBucket(minIOConfig.BucketName)
- .WithObject(ossRelativePath)
- .WithStreamData(memoryStream)
- .WithObjectSize(memoryStream.Length);
-
- await minioClient.PutObjectAsync(putObjectArgs);
- }
- else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
- {
- var awsConfig = ObjectStoreServiceOptions.AWS;
-
- var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
-
-
-
- //提供awsEndPoint(域名)进行访问配置
- var clientConfig = new AmazonS3Config
- {
- RegionEndpoint = RegionEndpoint.USEast1,
- UseHttp = true,
- };
-
- var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
-
- var putObjectRequest = new Amazon.S3.Model.PutObjectRequest()
- {
- BucketName = awsConfig.BucketName,
- InputStream = memoryStream,
- Key = ossRelativePath,
- };
-
- await amazonS3Client.PutObjectAsync(putObjectRequest);
- }
- else
- {
- throw new BusinessValidationFailedException("未定义的存储介质类型");
- }
+ await amazonS3Client.PutObjectAsync(putObjectRequest);
+ }
+ else
+ {
+ throw new BusinessValidationFailedException("未定义的存储介质类型");
}
}
- catch (Exception ex)
- {
-
- throw new BusinessValidationFailedException($"上传发生异常:{ex.Message}");
- }
-
-
-
-
- return "/" + ossRelativePath;
+ }
+ catch (Exception ex)
+ {
+ throw new BusinessValidationFailedException($"上传发生异常:{ex.Message}");
}
- ///
- /// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
- ///
- ///
- ///
- ///
- ///
- ///
- public async Task UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true)
- {
- var localFileName = Path.GetFileName(localFilePath);
- var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{localFileName}" : $"{oosFolderPath}/{localFileName}";
+ return "/" + ossRelativePath;
+
+ }
+
+
+
+ ///
+ /// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true)
+ {
+ var localFileName = Path.GetFileName(localFilePath);
+
+ var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{localFileName}" : $"{oosFolderPath}/{localFileName}";
+
+
+ if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
+ {
+ var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
+
+ var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
+
+ // 上传文件
+ var result = _ossClient.PutObject(aliConfig.BucketName, ossRelativePath, localFilePath);
+
+ }
+ else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
+ {
+ var minIOConfig = ObjectStoreServiceOptions.MinIO;
+
+
+ var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
+ .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
+ .Build();
+
+ var putObjectArgs = new PutObjectArgs()
+ .WithBucket(minIOConfig.BucketName)
+ .WithObject(ossRelativePath)
+ .WithFileName(localFilePath);
+
+ await minioClient.PutObjectAsync(putObjectArgs);
+ }
+ else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
+ {
+ var awsConfig = ObjectStoreServiceOptions.AWS;
+
+ // 提供awsAccessKeyId和awsSecretAccessKey构造凭证
+ var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
+
+ //提供awsEndPoint(域名)进行访问配置
+ var clientConfig = new AmazonS3Config
+ {
+ RegionEndpoint = RegionEndpoint.USEast1,
+ UseHttp = true,
+ };
+
+ var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
+
+ var putObjectRequest = new Amazon.S3.Model.PutObjectRequest()
+ {
+ BucketName = awsConfig.BucketName,
+ FilePath = localFilePath,
+ Key = ossRelativePath,
+ };
+
+ await amazonS3Client.PutObjectAsync(putObjectRequest);
+
+ }
+ else
+ {
+ throw new BusinessValidationFailedException("未定义的存储介质类型");
+ }
+ return "/" + ossRelativePath;
+
+ }
+
+
+ public async Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath)
+ {
+
+ ossRelativePath = ossRelativePath.TrimStart('/');
+ try
+ {
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
@@ -286,24 +355,31 @@ namespace IRaCIS.Core.Application.Helper
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
// 上传文件
- var result = _ossClient.PutObject(aliConfig.BucketName, ossRelativePath, localFilePath);
+ var result = _ossClient.GetObject(aliConfig.BucketName, ossRelativePath);
+
+ // 将下载的文件流保存到本地文件
+ using (var fs = File.OpenWrite(localFilePath))
+ {
+ result.Content.CopyTo(fs);
+ fs.Close();
+ }
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
{
var minIOConfig = ObjectStoreServiceOptions.MinIO;
-
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
.WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
.Build();
- var putObjectArgs = new PutObjectArgs()
- .WithBucket(minIOConfig.BucketName)
- .WithObject(ossRelativePath)
- .WithFileName(localFilePath);
+ var getObjectArgs = new GetObjectArgs()
+ .WithBucket(minIOConfig.BucketName)
+ .WithObject(ossRelativePath)
+ .WithFile(localFilePath);
+
+ await minioClient.GetObjectAsync(getObjectArgs);
- await minioClient.PutObjectAsync(putObjectArgs);
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
{
@@ -321,291 +397,85 @@ namespace IRaCIS.Core.Application.Helper
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
- var putObjectRequest = new Amazon.S3.Model.PutObjectRequest()
+ var getObjectArgs = new Amazon.S3.Model.GetObjectRequest()
{
BucketName = awsConfig.BucketName,
- FilePath = localFilePath,
Key = ossRelativePath,
};
- await amazonS3Client.PutObjectAsync(putObjectRequest);
+
+ await (await amazonS3Client.GetObjectAsync(getObjectArgs)).WriteResponseStreamToFileAsync(localFilePath, true, CancellationToken.None);
+
}
else
{
throw new BusinessValidationFailedException("未定义的存储介质类型");
}
- return "/" + ossRelativePath;
+ }
+ catch (Exception ex)
+ {
+ throw new BusinessValidationFailedException("oss下载失败!" + ex.Message);
}
- public async Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath)
+
+
+
+ }
+
+ public async Task GetSignedUrl(string ossRelativePath)
+ {
+ ossRelativePath = ossRelativePath.TrimStart('/');
+ try
{
- ossRelativePath = ossRelativePath.TrimStart('/');
- try
- {
-
- if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
- {
- var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
-
- var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
-
- // 上传文件
- var result = _ossClient.GetObject(aliConfig.BucketName, ossRelativePath);
-
- // 将下载的文件流保存到本地文件
- using (var fs = File.OpenWrite(localFilePath))
- {
- result.Content.CopyTo(fs);
- fs.Close();
- }
-
- }
- else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
- {
- var minIOConfig = ObjectStoreServiceOptions.MinIO;
-
- var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
- .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
- .Build();
-
- var getObjectArgs = new GetObjectArgs()
- .WithBucket(minIOConfig.BucketName)
- .WithObject(ossRelativePath)
- .WithFile(localFilePath);
-
- await minioClient.GetObjectAsync(getObjectArgs);
-
- }
- else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
- {
- var awsConfig = ObjectStoreServiceOptions.AWS;
-
- // 提供awsAccessKeyId和awsSecretAccessKey构造凭证
- var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
-
- //提供awsEndPoint(域名)进行访问配置
- var clientConfig = new AmazonS3Config
- {
- RegionEndpoint = RegionEndpoint.USEast1,
- UseHttp = true,
- };
-
- var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
-
- var getObjectArgs = new Amazon.S3.Model.GetObjectRequest()
- {
- BucketName = awsConfig.BucketName,
- Key = ossRelativePath,
- };
-
-
- await (await amazonS3Client.GetObjectAsync(getObjectArgs)).WriteResponseStreamToFileAsync(localFilePath, true, CancellationToken.None);
-
-
- }
- else
- {
- throw new BusinessValidationFailedException("未定义的存储介质类型");
- }
- }
- catch (Exception ex)
- {
-
- throw new BusinessValidationFailedException("oss下载失败!" + ex.Message);
- }
-
-
-
-
-
- }
-
- public async Task GetSignedUrl(string ossRelativePath)
- {
- ossRelativePath = ossRelativePath.TrimStart('/');
- try
- {
-
-
- if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
- {
- var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
-
- var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
-
- // 生成签名URL。
- var req = new GeneratePresignedUriRequest(aliConfig.BucketName, ossRelativePath, SignHttpMethod.Get)
- {
- // 设置签名URL过期时间,默认值为3600秒。
- Expiration = DateTime.Now.AddHours(1),
- };
- var uri = _ossClient.GeneratePresignedUri(req);
-
- return uri.PathAndQuery;
-
- }
- else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
- {
- var minIOConfig = ObjectStoreServiceOptions.MinIO;
-
- var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
- .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
- .Build();
-
-
- var args = new PresignedGetObjectArgs()
- .WithBucket(minIOConfig.BucketName)
- .WithObject(ossRelativePath)
- .WithExpiry(3600)
- /*.WithHeaders(reqParams)*/;
-
- var presignedUrl = await minioClient.PresignedGetObjectAsync(args);
-
- Uri uri = new Uri(presignedUrl);
-
- string relativePath = uri.PathAndQuery;
-
-
- return relativePath;
-
- }
- else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
- {
- var awsConfig = ObjectStoreServiceOptions.AWS;
-
-
- // 提供awsAccessKeyId和awsSecretAccessKey构造凭证
- var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
-
- //提供awsEndPoint(域名)进行访问配置
- var clientConfig = new AmazonS3Config
- {
- RegionEndpoint = RegionEndpoint.USEast1,
- UseHttp = true,
- };
-
- var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
-
- var presignedUrl = await amazonS3Client.GetPreSignedURLAsync(new GetPreSignedUrlRequest()
- {
- BucketName = awsConfig.BucketName,
- Key = ossRelativePath,
- Expires = DateTime.UtcNow.AddMinutes(120)
- });
-
- Uri uri = new Uri(presignedUrl);
-
- string relativePath = uri.PathAndQuery;
-
-
- return relativePath;
- }
- else
- {
- throw new BusinessValidationFailedException("未定义的存储介质类型");
- }
- }
- catch (Exception ex)
- {
-
- throw new BusinessValidationFailedException("oss授权url失败!" + ex.Message);
- }
-
- }
-
- ///
- /// 删除某个目录的文件
- ///
- ///
- ///
- public async Task DeleteFromPrefix(string prefix)
- {
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
{
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
-
- try
+ // 生成签名URL。
+ var req = new GeneratePresignedUriRequest(aliConfig.BucketName, ossRelativePath, SignHttpMethod.Get)
{
- ObjectListing objectListing = null;
- string nextMarker = null;
- do
- {
- // 使用 prefix 模拟目录结构,设置 MaxKeys 和 NextMarker
- objectListing = _ossClient.ListObjects(new Aliyun.OSS.ListObjectsRequest(aliConfig.BucketName)
- {
- Prefix = prefix,
- MaxKeys = 1000,
- Marker = nextMarker
- });
-
- List keys = objectListing.ObjectSummaries.Select(t => t.Key).ToList();
-
- // 删除获取到的文件
- if (keys.Count > 0)
- {
- _ossClient.DeleteObjects(new Aliyun.OSS.DeleteObjectsRequest(aliConfig.BucketName, keys, false));
- }
-
- // 设置 NextMarker 以获取下一页的数据
- nextMarker = objectListing.NextMarker;
-
- } while (objectListing.IsTruncated);
- }
- catch (Exception ex)
- {
- Console.WriteLine($"Error: {ex.Message}");
- }
+ // 设置签名URL过期时间,默认值为3600秒。
+ Expiration = DateTime.Now.AddHours(1),
+ };
+ var uri = _ossClient.GeneratePresignedUri(req);
+ return uri.PathAndQuery;
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
{
var minIOConfig = ObjectStoreServiceOptions.MinIO;
-
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
.WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
.Build();
- var listArgs = new ListObjectsArgs().WithBucket(minIOConfig.BucketName).WithPrefix(prefix).WithRecursive(true);
-
-
-
- // 创建一个空列表用于存储对象键
- var objects = new List();
-
- // 使用 await foreach 来异步迭代对象列表
- await foreach (var item in minioClient.ListObjectsEnumAsync(listArgs))
- {
- objects.Add(item.Key);
- }
-
-
- if (objects.Count > 0)
- {
- var objArgs = new RemoveObjectsArgs()
- .WithBucket(minIOConfig.BucketName)
- .WithObjects(objects);
-
- // 删除对象
- await minioClient.RemoveObjectsAsync(objArgs);
- }
+ var args = new PresignedGetObjectArgs()
+ .WithBucket(minIOConfig.BucketName)
+ .WithObject(ossRelativePath)
+ .WithExpiry(3600)
+ /*.WithHeaders(reqParams)*/;
+
+ var presignedUrl = await minioClient.PresignedGetObjectAsync(args);
+
+ Uri uri = new Uri(presignedUrl);
+
+ string relativePath = uri.PathAndQuery;
+ return relativePath;
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
{
-
var awsConfig = ObjectStoreServiceOptions.AWS;
@@ -621,144 +491,271 @@ namespace IRaCIS.Core.Application.Helper
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
- // 列出指定前缀下的所有对象
- var listObjectsRequest = new ListObjectsV2Request
+ var presignedUrl = await amazonS3Client.GetPreSignedURLAsync(new GetPreSignedUrlRequest()
{
BucketName = awsConfig.BucketName,
- Prefix = prefix
- };
+ Key = ossRelativePath,
+ Expires = DateTime.UtcNow.AddMinutes(120)
+ });
- var listObjectsResponse = await amazonS3Client.ListObjectsV2Async(listObjectsRequest);
-
- if (listObjectsResponse.S3Objects.Count > 0)
- {
- // 准备删除请求
- var deleteObjectsRequest = new Amazon.S3.Model.DeleteObjectsRequest
- {
- BucketName = awsConfig.BucketName,
- Objects = new List()
- };
-
- foreach (var s3Object in listObjectsResponse.S3Objects)
- {
- deleteObjectsRequest.Objects.Add(new KeyVersion
- {
- Key = s3Object.Key
- });
- }
-
- // 批量删除对象
- var deleteObjectsResponse = await amazonS3Client.DeleteObjectsAsync(deleteObjectsRequest);
- }
+ Uri uri = new Uri(presignedUrl);
+ string relativePath = uri.PathAndQuery;
+ return relativePath;
}
else
{
throw new BusinessValidationFailedException("未定义的存储介质类型");
}
}
-
-
-
-
- public async Task GetObjectStoreTempToken()
+ catch (Exception ex)
{
- var ossOptions = ObjectStoreServiceOptions.AliyunOSS;
- if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
- {
- var client = new Client(new AlibabaCloud.OpenApiClient.Models.Config()
- {
- AccessKeyId = ossOptions.AccessKeyId,
- AccessKeySecret = ossOptions.AccessKeySecret,
- //AccessKeyId = "LTAI5tJV76pYX5yPg1N9QVE8",
- //AccessKeySecret = "roRNLa9YG1of4pYruJGCNKBXEWTAWa",
-
- Endpoint = "sts.cn-hangzhou.aliyuncs.com"
- });
-
- var assumeRoleRequest = new AlibabaCloud.SDK.Sts20150401.Models.AssumeRoleRequest();
- // 将设置为自定义的会话名称,例如oss-role-session。
- assumeRoleRequest.RoleSessionName = $"session-name-{NewId.NextGuid()}";
- // 将替换为拥有上传文件到指定OSS Bucket权限的RAM角色的ARN。
- assumeRoleRequest.RoleArn = ossOptions.RoleArn;
- //assumeRoleRequest.RoleArn = "acs:ram::1899121822495495:role/webdirect";
- assumeRoleRequest.DurationSeconds = ossOptions.DurationSeconds;
- var runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();
- var response = client.AssumeRoleWithOptions(assumeRoleRequest, runtime);
- var credentials = response.Body.Credentials;
-
- var tempToken = new AliyunOSSTempToken()
- {
- AccessKeyId = credentials.AccessKeyId,
- AccessKeySecret = credentials.AccessKeySecret,
-
- //转为服务器时区,最后统一转为客户端时区
- Expiration = TimeZoneInfo.ConvertTimeFromUtc(DateTime.Parse(credentials.Expiration), TimeZoneInfo.Local),
- SecurityToken = credentials.SecurityToken,
-
-
- Region = ossOptions.Region,
- BucketName = ossOptions.BucketName,
- EndPoint = ossOptions.EndPoint,
- ViewEndpoint = ossOptions.ViewEndpoint,
-
- };
-
- AliyunOSSTempToken = tempToken;
-
- return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, AliyunOSS = tempToken };
- }
- else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
- {
- return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, MinIO = ObjectStoreServiceOptions.MinIO };
- }
- else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
- {
- var awsOptions = ObjectStoreServiceOptions.AWS;
-
- //aws 临时凭证
- // 创建 STS 客户端
- var stsClient = new AmazonSecurityTokenServiceClient(awsOptions.AccessKeyId, awsOptions.SecretAccessKey);
-
- // 使用 AssumeRole 请求临时凭证
- var assumeRoleRequest = new AssumeRoleRequest
- {
-
- RoleArn = awsOptions.RoleArn, // 角色 ARN
- RoleSessionName = $"session-name-{NewId.NextGuid()}",
- DurationSeconds = awsOptions.DurationSeconds // 临时凭证有效期
- };
-
- var assumeRoleResponse = await stsClient.AssumeRoleAsync(assumeRoleRequest);
-
- var credentials = assumeRoleResponse.Credentials;
-
- var tempToken = new AWSTempToken()
- {
- AccessKeyId = credentials.AccessKeyId,
- SecretAccessKey = credentials.SecretAccessKey,
- SessionToken = credentials.SessionToken,
- Expiration = credentials.Expiration,
- Region = awsOptions.Region,
- BucketName = awsOptions.BucketName,
- EndPoint = awsOptions.EndPoint,
- ViewEndpoint = awsOptions.ViewEndpoint,
-
- };
-
- AWSTempToken = tempToken;
- return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, AWS = tempToken };
- }
- else
- {
- throw new BusinessValidationFailedException("未定义的存储介质类型");
- }
+ throw new BusinessValidationFailedException("oss授权url失败!" + ex.Message);
}
}
+ ///
+ /// 删除某个目录的文件
+ ///
+ ///
+ ///
+ public async Task DeleteFromPrefix(string prefix)
+ {
+ if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
+ {
+ var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
+
+ var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
+
+
+ try
+ {
+ ObjectListing objectListing = null;
+ string nextMarker = null;
+ do
+ {
+ // 使用 prefix 模拟目录结构,设置 MaxKeys 和 NextMarker
+ objectListing = _ossClient.ListObjects(new Aliyun.OSS.ListObjectsRequest(aliConfig.BucketName)
+ {
+ Prefix = prefix,
+ MaxKeys = 1000,
+ Marker = nextMarker
+ });
+
+ List keys = objectListing.ObjectSummaries.Select(t => t.Key).ToList();
+
+ // 删除获取到的文件
+ if (keys.Count > 0)
+ {
+ _ossClient.DeleteObjects(new Aliyun.OSS.DeleteObjectsRequest(aliConfig.BucketName, keys, false));
+ }
+
+ // 设置 NextMarker 以获取下一页的数据
+ nextMarker = objectListing.NextMarker;
+
+ } while (objectListing.IsTruncated);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error: {ex.Message}");
+ }
+
+
+ }
+ else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
+ {
+ var minIOConfig = ObjectStoreServiceOptions.MinIO;
+
+
+ var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
+ .WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
+ .Build();
+
+
+ var listArgs = new ListObjectsArgs().WithBucket(minIOConfig.BucketName).WithPrefix(prefix).WithRecursive(true);
+
+
+
+ // 创建一个空列表用于存储对象键
+ var objects = new List();
+
+ // 使用 await foreach 来异步迭代对象列表
+ await foreach (var item in minioClient.ListObjectsEnumAsync(listArgs))
+ {
+ objects.Add(item.Key);
+ }
+
+
+ if (objects.Count > 0)
+ {
+ var objArgs = new RemoveObjectsArgs()
+ .WithBucket(minIOConfig.BucketName)
+ .WithObjects(objects);
+
+ // 删除对象
+ await minioClient.RemoveObjectsAsync(objArgs);
+ }
+
+
+
+ }
+ else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
+ {
+
+ var awsConfig = ObjectStoreServiceOptions.AWS;
+
+
+ // 提供awsAccessKeyId和awsSecretAccessKey构造凭证
+ var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
+
+ //提供awsEndPoint(域名)进行访问配置
+ var clientConfig = new AmazonS3Config
+ {
+ RegionEndpoint = RegionEndpoint.USEast1,
+ UseHttp = true,
+ };
+
+ var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
+
+ // 列出指定前缀下的所有对象
+ var listObjectsRequest = new ListObjectsV2Request
+ {
+ BucketName = awsConfig.BucketName,
+ Prefix = prefix
+ };
+
+ var listObjectsResponse = await amazonS3Client.ListObjectsV2Async(listObjectsRequest);
+
+ if (listObjectsResponse.S3Objects.Count > 0)
+ {
+ // 准备删除请求
+ var deleteObjectsRequest = new Amazon.S3.Model.DeleteObjectsRequest
+ {
+ BucketName = awsConfig.BucketName,
+ Objects = new List()
+ };
+
+ foreach (var s3Object in listObjectsResponse.S3Objects)
+ {
+ deleteObjectsRequest.Objects.Add(new KeyVersion
+ {
+ Key = s3Object.Key
+ });
+ }
+
+ // 批量删除对象
+ var deleteObjectsResponse = await amazonS3Client.DeleteObjectsAsync(deleteObjectsRequest);
+ }
+
+
+
+ }
+ else
+ {
+ throw new BusinessValidationFailedException("未定义的存储介质类型");
+ }
+ }
+
+
+
+
+ public async Task GetObjectStoreTempToken()
+ {
+ var ossOptions = ObjectStoreServiceOptions.AliyunOSS;
+
+ if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
+ {
+ var client = new Client(new AlibabaCloud.OpenApiClient.Models.Config()
+ {
+ AccessKeyId = ossOptions.AccessKeyId,
+ AccessKeySecret = ossOptions.AccessKeySecret,
+ //AccessKeyId = "LTAI5tJV76pYX5yPg1N9QVE8",
+ //AccessKeySecret = "roRNLa9YG1of4pYruJGCNKBXEWTAWa",
+
+ Endpoint = "sts.cn-hangzhou.aliyuncs.com"
+ });
+
+ var assumeRoleRequest = new AlibabaCloud.SDK.Sts20150401.Models.AssumeRoleRequest();
+ // 将设置为自定义的会话名称,例如oss-role-session。
+ assumeRoleRequest.RoleSessionName = $"session-name-{NewId.NextGuid()}";
+ // 将替换为拥有上传文件到指定OSS Bucket权限的RAM角色的ARN。
+ assumeRoleRequest.RoleArn = ossOptions.RoleArn;
+ //assumeRoleRequest.RoleArn = "acs:ram::1899121822495495:role/webdirect";
+ assumeRoleRequest.DurationSeconds = ossOptions.DurationSeconds;
+ var runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();
+ var response = client.AssumeRoleWithOptions(assumeRoleRequest, runtime);
+ var credentials = response.Body.Credentials;
+
+ var tempToken = new AliyunOSSTempToken()
+ {
+ AccessKeyId = credentials.AccessKeyId,
+ AccessKeySecret = credentials.AccessKeySecret,
+
+ //转为服务器时区,最后统一转为客户端时区
+ Expiration = TimeZoneInfo.ConvertTimeFromUtc(DateTime.Parse(credentials.Expiration), TimeZoneInfo.Local),
+ SecurityToken = credentials.SecurityToken,
+
+
+ Region = ossOptions.Region,
+ BucketName = ossOptions.BucketName,
+ EndPoint = ossOptions.EndPoint,
+ ViewEndpoint = ossOptions.ViewEndpoint,
+
+ };
+
+ AliyunOSSTempToken = tempToken;
+
+ return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, AliyunOSS = tempToken };
+ }
+ else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
+ {
+ return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, MinIO = ObjectStoreServiceOptions.MinIO };
+ }
+ else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
+ {
+ var awsOptions = ObjectStoreServiceOptions.AWS;
+
+ //aws 临时凭证
+ // 创建 STS 客户端
+ var stsClient = new AmazonSecurityTokenServiceClient(awsOptions.AccessKeyId, awsOptions.SecretAccessKey);
+
+ // 使用 AssumeRole 请求临时凭证
+ var assumeRoleRequest = new AssumeRoleRequest
+ {
+
+ RoleArn = awsOptions.RoleArn, // 角色 ARN
+ RoleSessionName = $"session-name-{NewId.NextGuid()}",
+ DurationSeconds = awsOptions.DurationSeconds // 临时凭证有效期
+ };
+
+ var assumeRoleResponse = await stsClient.AssumeRoleAsync(assumeRoleRequest);
+
+ var credentials = assumeRoleResponse.Credentials;
+
+ var tempToken = new AWSTempToken()
+ {
+ AccessKeyId = credentials.AccessKeyId,
+ SecretAccessKey = credentials.SecretAccessKey,
+ SessionToken = credentials.SessionToken,
+ Expiration = credentials.Expiration,
+ Region = awsOptions.Region,
+ BucketName = awsOptions.BucketName,
+ EndPoint = awsOptions.EndPoint,
+ ViewEndpoint = awsOptions.ViewEndpoint,
+
+ };
+
+ AWSTempToken = tempToken;
+ return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, AWS = tempToken };
+ }
+ else
+ {
+ throw new BusinessValidationFailedException("未定义的存储介质类型");
+ }
+ }
}
diff --git a/IRaCIS.Core.Application/Helper/WordTempleteHelper.cs b/IRaCIS.Core.Application/Helper/WordTempleteHelper.cs
index 7fc34987b..2668892ee 100644
--- a/IRaCIS.Core.Application/Helper/WordTempleteHelper.cs
+++ b/IRaCIS.Core.Application/Helper/WordTempleteHelper.cs
@@ -4,93 +4,92 @@ using System.Globalization;
using Xceed.Document.NET;
using Xceed.Words.NET;
-namespace IRaCIS.Core.Application.Helper
+namespace IRaCIS.Core.Application.Helper;
+
+///
+/// 利用DocX 库 处理word国际化模板
+///
+public static class WordTempleteHelper
{
- ///
- /// 利用DocX 库 处理word国际化模板
- ///
- public static class WordTempleteHelper
+ public static void DocX_GetInternationalTempleteStream(string filePath, Stream memoryStream)
{
- public static void DocX_GetInternationalTempleteStream(string filePath, Stream memoryStream)
+
+ var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
+
+ using (DocX document = DocX.Load(filePath))
{
+ // 查找书签
+ var bookmarkEn_Start = document.Bookmarks.FirstOrDefault(b => b.Name == StaticData.CultureInfo.en_US_bookMark);
- var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
-
- using (DocX document = DocX.Load(filePath))
+ if (bookmarkEn_Start != null)
{
- // 查找书签
- var bookmarkEn_Start = document.Bookmarks.FirstOrDefault(b => b.Name == StaticData.CultureInfo.en_US_bookMark);
+ // 获取书签的起始位置
+ //int bookmarkCNStartPos = bookmarkCn_Start.Paragraph.StartIndex;
- if (bookmarkEn_Start != null)
+ var bookmarkENStartPos = bookmarkEn_Start.Paragraph.StartIndex;
+
+ // 创建一个要删除段落的列表
+ List paragraphsToRemove = new List();
+
+ foreach (var item in document.Paragraphs)
{
- // 获取书签的起始位置
- //int bookmarkCNStartPos = bookmarkCn_Start.Paragraph.StartIndex;
+ //中文模板在前,英文在后,英文模板,就删除英文之前的,中文模板就删除英文之后的
- var bookmarkENStartPos = bookmarkEn_Start.Paragraph.StartIndex;
-
- // 创建一个要删除段落的列表
- List paragraphsToRemove = new List();
-
- foreach (var item in document.Paragraphs)
+ if (isEn_US ? item.EndIndex < bookmarkENStartPos : item.StartIndex >= bookmarkENStartPos)
{
- //中文模板在前,英文在后,英文模板,就删除英文之前的,中文模板就删除英文之后的
-
- if (isEn_US ? item.EndIndex < bookmarkENStartPos : item.StartIndex >= bookmarkENStartPos)
- {
- paragraphsToRemove.Add(item);
- }
+ paragraphsToRemove.Add(item);
}
-
- foreach (var paragraph in paragraphsToRemove)
- {
- document.RemoveParagraph(paragraph);
- }
-
}
- // 保存修改
- document.SaveAs(memoryStream);
- }
- }
-
-
- public static void Npoi_GetInternationalTempleteStream(string filePath, Stream memoryStream)
- {
-
- var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
-
- using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
- {
- XWPFDocument doc = new XWPFDocument(fs);
-
- // 查找包含指定书签的段落及其索引
- var bookmarkParagraph = doc.Paragraphs
- .FirstOrDefault(p => p.GetCTP().GetBookmarkStartList().Any(b => b.name == StaticData.CultureInfo.en_US_bookMark));
-
- if (bookmarkParagraph != null)
+ foreach (var paragraph in paragraphsToRemove)
{
- int bookmarkIndex = doc.Paragraphs.IndexOf(bookmarkParagraph);
-
- if (isEn_US)
- {
- // 从书签所在段落开始,删除之前的所有段落
- for (int i = bookmarkIndex - 1; i >= 0; i--)
- {
- doc.RemoveBodyElement(i);
- }
- }
- else
- {
- // 删除书签之后的所有段落
- for (int i = doc.Paragraphs.Count - 1; i >= bookmarkIndex; i--)
- {
- doc.RemoveBodyElement(i);
- }
- }
+ document.RemoveParagraph(paragraph);
}
- doc.Write(memoryStream);
- }
- }
+ }
+
+ // 保存修改
+ document.SaveAs(memoryStream);
+ }
}
+
+
+ public static void Npoi_GetInternationalTempleteStream(string filePath, Stream memoryStream)
+ {
+
+ var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
+
+ using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
+ {
+ XWPFDocument doc = new XWPFDocument(fs);
+
+ // 查找包含指定书签的段落及其索引
+ var bookmarkParagraph = doc.Paragraphs
+ .FirstOrDefault(p => p.GetCTP().GetBookmarkStartList().Any(b => b.name == StaticData.CultureInfo.en_US_bookMark));
+
+ if (bookmarkParagraph != null)
+ {
+ int bookmarkIndex = doc.Paragraphs.IndexOf(bookmarkParagraph);
+
+ if (isEn_US)
+ {
+ // 从书签所在段落开始,删除之前的所有段落
+ for (int i = bookmarkIndex - 1; i >= 0; i--)
+ {
+ doc.RemoveBodyElement(i);
+ }
+ }
+ else
+ {
+ // 删除书签之后的所有段落
+ for (int i = doc.Paragraphs.Count - 1; i >= bookmarkIndex; i--)
+ {
+ doc.RemoveBodyElement(i);
+ }
+ }
+ }
+ doc.Write(memoryStream);
+ }
+ }
+
}