using Aliyun.Acs.Core.Exceptions; using Aliyun.OSS; using Aliyun.OSS.Util; using cylsg.utility; using cylsg.utility.Extend; using EzTencentCloud; using Furion; using Furion.DependencyInjection; using Furion.FriendlyException; using Microsoft.AspNetCore.Http; using SqlSugar; using System.Drawing; using System.Globalization; using System.Security.Cryptography; using System.Text; using Tea; using TencentCloud.Ocr.V20181119.Models; using Task = System.Threading.Tasks.Task; using Newtonsoft.Json; using static AlibabaCloud.SDK.Sts20150401.Models.AssumeRoleResponseBody; namespace EzUpFile { /// /// 附件服务程序 /// public class EzFileUploadService : IEzFileUploadService, IScoped { private readonly HttpRequest? _request; private readonly ISqlSugarClient _sqlSugarClient; private readonly ITencentCloudService _tcs; public EzFileUploadService(IHttpContextAccessor httpContext, ISqlSugarClient sqlSugarClient, ITencentCloudService tencentCloudService) { _request = httpContext.HttpContext?.Request ?? null; _sqlSugarClient = sqlSugarClient; _tcs = tencentCloudService; } /// /// 上传附件 /// /// public async Task UploadFiles() { var maxSize = 1024 * 1024 * 5; //上传大小5M var file = _request?.Form?.Files["file"]; if (file == null) { throw Oops.Oh("你没有选择文件"); } var fileName = file.FileName; var fileExt = Path.GetExtension(fileName).ToLowerInvariant(); //检查大小 if (file.Length > maxSize) { throw Oops.Oh("文件大于设置文件"); } ////检查文件扩展名 //if (string.IsNullOrEmpty(fileExt) || Array.IndexOf(op.AttachmentSaveFileExtName?.Split(',') ?? new string[] { "" }, fileExt.Substring(1).ToLower()) == -1) //{ // throw Oops.Oh("上传文件扩展名是不允许的扩展名,请上传后缀名为:" + op.AttachmentSaveFileExtName); //} string url = string.Empty; url = await UpLoadFileForAliYunOSS(fileExt, file); return url; } /// /// 上传base64 /// /// /// public async Task UploadFilesFByBase64(string base64) { if (string.IsNullOrEmpty(base64)) { throw Oops.Oh("没有内容"); } //检查上传大小 if (!CommonHelper.CheckBase64Size(base64, 5)) { throw Oops.Oh("上传文件大小超过限制,最大允许上传" + "5" + "M"); } base64 = base64.Replace("data:image/png;base64,", "").Replace("data:image/jgp;base64,", "").Replace("data:image/jpg;base64,", "").Replace("data:image/jpeg;base64,", "");//将base64头部信息替换 byte[] bytes = Convert.FromBase64String(base64); MemoryStream memStream = new MemoryStream(bytes); string url = string.Empty; url = await UpLoadBase64ForAliYunOSS(memStream); return url; } /// /// 删除文件 /// /// /// public async Task DelFile(string Path) { var ret = await DelFileForAliYunOSS(Path); return ret; } #region 阿里云上传方法(File) /// /// 阿里云上传方法(File) /// /// /// /// /// public async Task UpLoadFileForAliYunOSS(string fileExt, IFormFile file) { var newFileName = DateTime.Now.ToString("yyyyMMddHHmmss_ffff", DateTimeFormatInfo.InvariantInfo) + fileExt; var today = DateTime.Now.ToString("yyyyMMdd"); //上传到阿里云 await using var fileStream = file.OpenReadStream(); var md5 = OssUtils.ComputeContentMd5(fileStream, file.Length); var filePath = App.Configuration["FileUploadOptions:SavePath"] + today + "/" + newFileName; //云文件保存路径 //初始化阿里云配置--外网Endpoint、访问ID、访问password var aliYun = new OssClient(App.Configuration["FileUploadOptions:AliOSSEndpoint"], App.Configuration["FileUploadOptions:AliOSSAccessKeyID"], App.Configuration["FileUploadOptions:AliOSSAccessKeySecret"]); //将文件md5值赋值给meat头信息,服务器验证文件MD5 var objectMeta = new ObjectMetadata { ContentMd5 = md5 }; var task = Task.Run(() => //文件上传--空间名、文件保存路径、文件流、meta头信息(文件md5) //返回meta头信息(文件md5) aliYun.PutObject(App.Configuration["FileUploadOptions:AliOSSBucketName"], filePath, fileStream, objectMeta) ); //等待完成 try { task.Wait(); } catch (AggregateException ex) { throw Oops.Oh(ex.Message); } return App.Configuration["FileUploadOptions:AliOSSSaveBaseUrl"] + filePath; } #endregion #region 阿里云上传方法(Base64) /// /// 阿里云上传方法(Base64) /// /// /// /// public async Task UpLoadBase64ForAliYunOSS(MemoryStream memStream) { var newFileName = DateTime.Now.ToString("yyyyMMddHHmmss_ffff", DateTimeFormatInfo.InvariantInfo) + ".jpg"; var today = DateTime.Now.ToString("yyyyMMdd"); // 设置当前流的位置为流的开始 memStream.Seek(0, SeekOrigin.Begin); await using var fileStream = memStream; var md5 = OssUtils.ComputeContentMd5(fileStream, memStream.Length); var filePath = App.Configuration["FileUploadOptions:SavePath"] + today + "/" + newFileName; //云文件保存路径 //初始化阿里云配置--外网Endpoint、访问ID、访问password var aliYun = new OssClient(App.Configuration["FileUploadOptions:AliOSSEndpoint"], App.Configuration["FileUploadOptions:AliOSSAccessKeyID"], App.Configuration["FileUploadOptions:AliOSSAccessKeySecret"]); //将文件md5值赋值给meat头信息,服务器验证文件MD5 var objectMeta = new ObjectMetadata { ContentMd5 = md5 }; try { //文件上传--空间名、文件保存路径、文件流、meta头信息(文件md5) //返回meta头信息(文件md5) aliYun.PutObject(App.Configuration["FileUploadOptions:AliOSSBucketName"], filePath, fileStream, objectMeta); } catch (AggregateException ex) { throw Oops.Oh(ex.Message); } //返回给UEditor的插入编辑器的图片的src return App.Configuration["FileUploadOptions:AliOSSSaveBaseUrl"] + filePath; } #endregion #region 删除文件 /// /// 阿里云删除 /// /// /// 带xxx.xx的链接地址 /// public async Task DelFileForAliYunOSS(string fileUrl) { //初始化阿里云配置--外网Endpoint、访问ID、访问password var aliYun = new OssClient(App.Configuration["FileUploadOptions:AliOSSEndpoint"], App.Configuration["FileUploadOptions:AliOSSAccessKeyID"], App.Configuration["FileUploadOptions:AliOSSAccessKeySecret"]); try { var task = Task.Run(() => aliYun.DeleteObject(App.Configuration["FileUploadOptions:AliOSSBucketName"], (App.Configuration["FileUploadOptions:SavePath"]?.RemoveStartWithStr("/") ?? "") + fileUrl.GetFileName())); task.Wait(); } catch (Exception ex) { throw Oops.Oh(ex.Message); } //返回给UEditor的插入编辑器的图片的src return true; } #endregion #region 识别上传 public async Task<(IDCardOCRResponse, string)> UpIdCord(string PageName = "FRONT") { try { var maxSize = 1024 * 1024 * 5; //上传大小5M var FileData = _request?.Form?.Files["file"]; if (FileData.Length > maxSize) { throw Oops.Oh(" 上传文件不可超出5M"); } //处理图形 // var FileData = Request.Form.Files[0]; Image oimage = Image.FromStream(FileData.OpenReadStream()); if (oimage == null) { throw Oops.Oh(" 上传失败"); } MemoryStream ms = new MemoryStream(); if (oimage.Width > 1200) { if (oimage.Width > oimage.Height) oimage.GetThumbnailImage(1200, 800, null, IntPtr.Zero).Save(ms, System.Drawing.Imaging.ImageFormat.Png); else oimage.GetThumbnailImage(800, 1200, null, IntPtr.Zero).Save(ms, System.Drawing.Imaging.ImageFormat.Png); } else oimage.Save(ms, System.Drawing.Imaging.ImageFormat.Png); ms.Position = 0; var arr = ms.ToArray(); string img64 = Convert.ToBase64String(arr); IDCardOCRResponse idcordinfo = null; string url = ""; try { idcordinfo = _tcs.IdCord(img64, PageName == "FRONT"); url = await UploadFilesFByBase64(_tcs.GetIdCordImg()); idcordinfo.AdvancedInfo = null; return (idcordinfo, url); } catch (Exception e) { throw Oops.Oh(e.Message + "腾讯云,或者阿里云操作错误"); } } catch (Exception e) { throw Oops.Oh(e.Message); } } public async Task<(BizLicenseOCRResponse, string)> UpBizLicense() { try { var maxSize = 1024 * 1024 * 5; //上传大小5M var FileData = _request?.Form?.Files["file"]; if (FileData.Length > maxSize) { throw Oops.Oh(" 上传文件不可超出5M"); } //处理图形 // var FileData = Request.Form.Files[0]; Image oimage = Image.FromStream(FileData.OpenReadStream()); if (oimage == null) { throw Oops.Oh(" 上传失败"); } MemoryStream ms = new MemoryStream(); if (oimage.Width > 1200) { if (oimage.Width > oimage.Height) oimage.GetThumbnailImage(1200, 800, null, IntPtr.Zero).Save(ms, System.Drawing.Imaging.ImageFormat.Png); else oimage.GetThumbnailImage(800, 1200, null, IntPtr.Zero).Save(ms, System.Drawing.Imaging.ImageFormat.Png); } else oimage.Save(ms, System.Drawing.Imaging.ImageFormat.Png); ms.Position = 0; var arr = ms.ToArray(); string img64 = Convert.ToBase64String(arr); BizLicenseOCRResponse info = null; string url = ""; try { info = _tcs.BizLicenseOCR(img64); url = await UploadFilesFByBase64(img64); return (info, url); } catch (Exception e) { throw Oops.Oh(e.Message); } } catch (Exception e) { throw Oops.Oh(e.Message); } } public async Task<(bool, string)> IaiAddPerso(string CoredID, string Name, int PersonGender) { try { var maxSize = 1024 * 1024 * 5; //上传大小5M var FileData = _request?.Form?.Files["file"]; if (FileData.Length > maxSize) { throw Oops.Oh(" 上传文件不可超出500K"); } //处理图形 // var FileData = Request.Form.Files[0]; Image oimage = Image.FromStream(FileData.OpenReadStream()); if (oimage == null) { throw Oops.Oh(" 上传失败"); } MemoryStream ms = new MemoryStream(); if (oimage.Width > 600) { if (oimage.Width > oimage.Height) oimage.GetThumbnailImage(600, 400, null, IntPtr.Zero).Save(ms, System.Drawing.Imaging.ImageFormat.Png); else oimage.GetThumbnailImage(400, 600, null, IntPtr.Zero).Save(ms, System.Drawing.Imaging.ImageFormat.Png); } else oimage.Save(ms, System.Drawing.Imaging.ImageFormat.Png); ms.Position = 0; var arr = ms.ToArray(); string img64 = Convert.ToBase64String(arr); bool info = false; string url = ""; try { info = _tcs.IaiAddPerso(img64, CoredID, Name, PersonGender); url = await UploadFilesFByBase64(img64); return (info, url); } catch (Exception e) { throw Oops.Oh(e.Message); } } catch (Exception e) { throw Oops.Oh(e.Message); } } /// public async Task<(bool, string)> IaiAddPerso(string imgBase64, string CoredID, string Name, int PersonGender) { if (string.IsNullOrEmpty(imgBase64)) { throw Oops.Oh("没有内容"); } //检查上传大小 if (!CommonHelper.CheckBase64Size(imgBase64, 5)) { throw Oops.Oh("上传文件大小超过限制,最大允许上传" + "5" + "M"); } imgBase64 = imgBase64.Replace("data:image/png;base64,", "").Replace("data:image/jgp;base64,", "").Replace("data:image/jpg;base64,", "").Replace("data:image/jpeg;base64,", "");//将base64头部信息替换 bool info = false; string url = ""; try { info = _tcs.IaiAddPerso(imgBase64, CoredID, Name, PersonGender); url = await UploadFilesFByBase64(imgBase64); return (info, url); } catch (Exception e) { throw Oops.Oh(e.Message); } } #endregion #region 本地上传云服务器凭证计算 public Dictionary GetToken1() { var dir = DateTime.Now.ToString("yyyyMMdd") + "/"; // 构造OssClient实例。 endpoint 格式:https://oss-cn-beijing.aliyuncs.com // var ossClient = new OssClient( App.Configuration["FileUploadOptions:AliOSSSaveBaseUrl"], App.Configuration["FileUploadOptions:AliOSSAccessKeyID"], App.Configuration["FileUploadOptions:AliOSSAccessKeySecret"]); var rt = GetSTSToken(); String securityToken = rt.AccessKeySecret; //获取Token var config = new PolicyConditions(); config.AddConditionItem(PolicyConditions.CondContentLengthRange, 1, 1024L * 1024 * 1024 * 5);// 文件大小范围:单位byte config.AddConditionItem(MatchMode.StartWith, PolicyConditions.CondKey, dir); //捅名 config.AddConditionItem("bucket", App.Configuration["FileUploadOptions:AliOSSBucketName"]); config.AddConditionItem("x-oss-signature-version", "OSS4-HMAC-SHA256"); config.AddConditionItem("x-oss-security-token", securityToken); // //请求时间 config.AddConditionItem("x-oss-date", DateTime.Now.ToString("yyyyMMdd'T'HHmmss'Z'")); config.AddConditionItem("x-oss-credential", App.Configuration["FileUploadOptions:AliOSSAccessKeyID"] + "/" + DateTime.Now.ToString("yyyyMMdd") + "/cn-chengdu/oss/aliyun_v4_request"); var expire = DateTimeOffset.Now.AddMinutes(30);// 过期时间 // 生成 Policy,并进行 Base64 编码 // var policy = ossClient.GeneratePostPolicy(expire.LocalDateTime, config); // var policyBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(policy)); // 计算签名 var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(App.Configuration["FileUploadOptions:AliOSSAccessKeySecret"])); // var bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(policyBase64)); // var sign = Convert.ToBase64String(bytes); return new Dictionary(); } public static AlibabaCloud.SDK.Sts20150401.Client CreateClient() { // 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。 // 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378671.html。 AlibabaCloud.OpenApiClient.Models.Config config = new AlibabaCloud.OpenApiClient.Models.Config { // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。 AccessKeyId = "LTAI5tKegnEbaSRPFRwDxeFd", // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。 AccessKeySecret = "9Hv6VYgWhpDHCMkwMLHiqF6ihusjdl", }; // Endpoint 请参考 https://api.aliyun.com/product/Sts config.Endpoint = "sts.cn-chengdu.aliyuncs.com"; return new AlibabaCloud.SDK.Sts20150401.Client(config); } /// /// 获取临时凭证 /// public static AssumeRoleResponseBodyCredentials GetSTSToken() { AlibabaCloud.SDK.Sts20150401.Client client = CreateClient(); AlibabaCloud.SDK.Sts20150401.Models.AssumeRoleRequest assumeRoleRequest = new AlibabaCloud.SDK.Sts20150401.Models.AssumeRoleRequest { Policy = "{\"Statement\": [{\"Action\": [\"*\"],\"Effect\": \"Allow\",\"Resource\": [\"*\"]}],\"Version\":\"1\"}", DurationSeconds = 3600, RoleArn = "acs:ram::1299465997752835:role/weixinupdatarl", RoleSessionName = "weixinupdataRl", }; AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions(); try { // 复制代码运行请自行打印 API 的返回值 var data = client.AssumeRoleWithOptions(assumeRoleRequest, runtime); if (data.StatusCode == 200) { return data.Body?.Credentials; } throw Oops.Oh("阿里云获取临时凭证错误"); } catch (TeaException error) { AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message); throw; } catch (Exception _error) { TeaException error = new TeaException(new Dictionary { { "message", _error.Message } }); AlibabaCloud.TeaUtil.Common.AssertAsString(error.Message); throw error; } } /// /// /// /// public Dictionary GetToken() { // 获取环境变量 string regionId = "cn-chengdu"; string roleSessionName = "weixinupdataRl"; // 定义STS临时访问凭证变量 string stsAccessKeyId = null; string stsSecretAccessKey = null; string securityToken = null; try { var rt = GetSTSToken(); stsAccessKeyId = rt.AccessKeyId; stsSecretAccessKey = rt.AccessKeySecret; securityToken = rt.SecurityToken; } catch (ServerException e) { throw; } catch (ClientException e) { throw; } // 格式化请求日期 DateTimeOffset now = DateTimeOffset.UtcNow; string dtObj1 = now.ToString("yyyyMMdd'T'HHmmss'Z'", CultureInfo.InvariantCulture); string dtObj2 = now.ToString("yyyyMMdd", CultureInfo.InvariantCulture); string expirationTime = now.AddHours(3).ToString("yyyy-MM-dd'T'HH:mm:ss.fff'Z'", CultureInfo.InvariantCulture); // 创建policy Dictionary policy = new Dictionary { { "expiration", expirationTime }, { "conditions", new List { new Dictionary { { "bucket", App.Configuration["FileUploadOptions:AliOSSBucketName"] } }, // 请将替换为您的实际Bucket名称 new Dictionary { { "x-oss-signature-version", "OSS4-HMAC-SHA256" } }, new Dictionary { { "x-oss-credential", $"{stsAccessKeyId}/{dtObj2}/{regionId}/oss/aliyun_v4_request" } }, // 请将替换为您的实际Bucket所处地域,例如北京地域为:cn-beijing new Dictionary { { "x-oss-security-token", securityToken } }, new Dictionary { { "x-oss-date", dtObj1 } } } } }; string jsonPolicy = JsonConvert.SerializeObject(policy); // 构造待签名字符串(StringToSign) string stringToSign = Convert.ToBase64String(Encoding.UTF8.GetBytes(jsonPolicy)); // 计算SigningKey byte[] dateKey = HmacSha256("aliyun_v4" + stsSecretAccessKey, dtObj2); byte[] dateRegionKey = HmacSha256(dateKey, regionId); // 请将替换为您的实际Bucket所处地域,例如北京地域为:cn-beijing byte[] dateRegionServiceKey = HmacSha256(dateRegionKey, "oss"); byte[] signingKey = HmacSha256(dateRegionServiceKey, "aliyun_v4_request"); // 计算Signature byte[] result = HmacSha256(signingKey, stringToSign); string signature = BitConverter.ToString(result).Replace("-", "").ToLower(); Dictionary messageMap = new Dictionary { { "security_token", securityToken }, { "signature", signature }, { "x_oss_date", dtObj1 }, { "x_oss_credential", $"{stsAccessKeyId}/{dtObj2}/{regionId}/oss/aliyun_v4_request" }, // 请将替换为您的实际Bucket所处地域,例如北京地域为:cn-beijing { "x_oss_signature_version", "OSS4-HMAC-SHA256" }, { "policy", stringToSign } }; // 打印返回至客户端的签名信息 return messageMap; } private static byte[] HmacSha256(byte[] key, string message) { using (HMACSHA256 hmac = new HMACSHA256(key)) { return hmac.ComputeHash(Encoding.UTF8.GetBytes(message)); } } private static byte[] HmacSha256(string key, string message) { using (HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key))) { return hmac.ComputeHash(Encoding.UTF8.GetBytes(message)); } } #endregion } }