using Aliyun.OSS; using Aliyun.OSS.Util; using COSXML; using COSXML.Auth; using EzCoreNet.Utility; using EzCoreNet.Utility.Extend; using EzCoreNetFurion.IServices; using EzCoreNetFurion.IServices.SysSet; using EzCoreNetFurion.Model.Emun; using Furion; using Furion.DependencyInjection; using Furion.FriendlyException; using Microsoft.AspNetCore.Http; using Qiniu.Storage; using Qiniu.Util; using SqlSugar; using System.Globalization; namespace EzUpFiles { /// /// 附件服务程序 /// public class EzFileUploadService : IEzFileUploadService, IScoped { private readonly ISYSSettingService _SYSSetting; private readonly HttpRequest? _request; private readonly ISqlSugarClient _sqlSugarClient; public EzFileUploadService(ISYSSettingService sYSSetting, IHttpContextAccessor httpContext, ISqlSugarClient sqlSugarClient) { _SYSSetting = sYSSetting; _request = httpContext.HttpContext?.Request ?? null; _sqlSugarClient = sqlSugarClient; } /// /// 上传附件 /// /// public async Task UploadFiles() { var op = _SYSSetting.GetAttachmentSetting(); if (op == null) throw Oops.Oh("你没有对附件保存进行设置,请设置附件保存"); var maxSize = 1024 * 1024 * (op.AttachmentSaveFileSize?.toInt() ?? 0); //上传大小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; switch (op.AttachmentSaveMode) { case AttachmentSaveMode.AliOSS: url = await UpLoadFileForAliYunOSS(op, fileExt, file); break; case AttachmentSaveMode.TencentCOS: url = await UpLoadFileForQCloudOSS(op, fileExt, file); break; case AttachmentSaveMode.QiNiuKodo: url = await UpLoadFileForQiNiuKoDo(op, fileExt, file); break; case AttachmentSaveMode.Logical: url = await UpLoadFileForLocalStorage(op, fileExt, file); break; case AttachmentSaveMode.DataBase: throw Oops.Oh("不支持"); break; default: break; } return url; } /// /// 上传base64 /// /// /// public async Task UploadFilesFByBase64(string base64) { var op = _SYSSetting.GetAttachmentSetting(); if (op == null) throw Oops.Oh("你没有对附件保存进行设置,请设置附件保存"); if (string.IsNullOrEmpty(base64)) { throw Oops.Oh("没有内容"); } //检查上传大小 if (!CommonHelper.CheckBase64Size(base64, op.AttachmentSaveFileSize?.toInt() ?? 5)) { throw Oops.Oh("上传文件大小超过限制,最大允许上传" + op.AttachmentSaveFileSize + "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; switch (op.AttachmentSaveMode) { case AttachmentSaveMode.AliOSS: url = await UpLoadBase64ForAliYunOSS(op, memStream); break; case AttachmentSaveMode.TencentCOS: url = await UpLoadBase64ForQCloudOSS(op, bytes); break; case AttachmentSaveMode.QiNiuKodo: url = await UpLoadBase64ForQiNiuKoDo(op, bytes); break; case AttachmentSaveMode.Logical: url = await UpLoadBase64ForLocalStorage(op, memStream); break; case AttachmentSaveMode.DataBase: throw Oops.Oh("不支持"); break; default: break; } return url; } /// /// 删除文件 /// /// /// public async Task DelFile(string Path) { var op = _SYSSetting.GetAttachmentSetting(); if (op == null) throw Oops.Oh("你没有对附件保存进行设置,请设置附件保存"); bool ret = false; switch (op.AttachmentSaveMode) { case AttachmentSaveMode.AliOSS: ret = await DelFileForAliYunOSS(op, Path); break; case AttachmentSaveMode.TencentCOS: ret = await DelFileForQCloudOSS(op, Path); break; case AttachmentSaveMode.QiNiuKodo: ret = await DelFileForQiNiuKoDo(op, Path); break; case AttachmentSaveMode.Logical: ret = await DelFileForLocalStorage(op, Path); break; case AttachmentSaveMode.DataBase: throw Oops.Oh("不支持"); default: break; } return ret; } #region 本地上传方法(File) /// /// 本地上传方法(File) /// /// /// /// /// public async Task UpLoadFileForLocalStorage(SYSDictionaryAttachmentSetting options, string fileExt, IFormFile file) { var newFileName = DateTime.Now.ToString("yyyyMMddHHmmss_ffff", DateTimeFormatInfo.InvariantInfo) + fileExt; var today = DateTime.Now.ToString("yyyyMMdd"); var saveUrl = options.AttachmentSavePath + today + "/"; var dirPath = App.WebHostEnvironment.WebRootPath + saveUrl; if (!Directory.Exists(dirPath)) Directory.CreateDirectory(dirPath); var filePath = dirPath + newFileName; var fileUrl = saveUrl + newFileName; await using (var fs = File.Create(filePath)) { await file.CopyToAsync(fs); fs.Flush(); } return options.AttachmentSave_LogicalSaveBaseUrl + fileUrl; } #endregion #region 阿里云上传方法(File) /// /// 阿里云上传方法(File) /// /// /// /// /// public async Task UpLoadFileForAliYunOSS(SYSDictionaryAttachmentSetting options, 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 = options.AttachmentSavePath + today + "/" + newFileName; //云文件保存路径 //初始化阿里云配置--外网Endpoint、访问ID、访问password var aliYun = new OssClient(options.AttachmentSave_AliOSSEndpoint, options.AttachmentSave_AliOSSAccessKeyID, options.AttachmentSave_AliOSSAccessKeySecret); //将文件md5值赋值给meat头信息,服务器验证文件MD5 var objectMeta = new ObjectMetadata { ContentMd5 = md5 }; var task = Task.Run(() => //文件上传--空间名、文件保存路径、文件流、meta头信息(文件md5) //返回meta头信息(文件md5) aliYun.PutObject(options.AttachmentSave_AliOSSBucketName, filePath, fileStream, objectMeta) ); //等待完成 try { task.Wait(); } catch (AggregateException ex) { throw Oops.Oh(ex.Message); } //返回给UEditor的插入编辑器的图片的src return options.AttachmentSave_AliOSSSaveBaseUrl + filePath; } #endregion #region 腾讯云存储上传方法(File) /// /// 腾讯云存储上传方法(File) /// /// /// /// /// public async Task UpLoadFileForQCloudOSS(SYSDictionaryAttachmentSetting options, string fileExt, IFormFile file) { var newFileName = DateTime.Now.ToString("yyyyMMddHHmmss_ffff", DateTimeFormatInfo.InvariantInfo) + fileExt; var today = DateTime.Now.ToString("yyyyMMdd"); var filePath = options.AttachmentSavePath + today + "/" + newFileName; //云文件保存路径 //上传到腾讯云OSS //初始化 CosXmlConfig string appid = options.AttachmentSave_TencentAPPID;//设置腾讯云账户的账户标识 APPID string region = options.AttachmentSave_TencentCosRegion; //设置一个默认的存储桶地域 CosXmlConfig config = new CosXmlConfig.Builder() //.SetAppid(appid) .IsHttps(true) //设置默认 HTTPS 请求 .SetRegion(region) //设置一个默认的存储桶地域 .SetDebugLog(true) //显示日志 .Build(); //创建 CosXmlConfig 对象 long durationSecond = 600; //每次请求签名有效时长,单位为秒 QCloudCredentialProvider qCloudCredentialProvider = new DefaultQCloudCredentialProvider(options.AttachmentSave_TencentSecretId, options.AttachmentSave_TencentSecretKey, durationSecond); byte[] bytes; await using (var ms = new MemoryStream()) { await file.CopyToAsync(ms); bytes = ms.ToArray(); } try { var cosXml = new CosXmlServer(config, qCloudCredentialProvider); COSXML.Model.Object.PutObjectRequest putObjectRequest = new COSXML.Model.Object.PutObjectRequest(options.AttachmentSave_TencentBucketName, filePath, bytes); cosXml.PutObject(putObjectRequest); } catch (COSXML.CosException.CosClientException clientEx) { throw Oops.Oh(clientEx.Message); } catch (COSXML.CosException.CosServerException serverEx) { throw Oops.Oh(serverEx.GetInfo); } return options.AttachmentSave_TencentSaveBaseUrl + filePath; } #endregion #region 七牛云存储上传(File) /// /// 七牛云存储上传(File) /// /// /// /// /// public async Task UpLoadFileForQiNiuKoDo(SYSDictionaryAttachmentSetting options, string fileExt, IFormFile file) { var newFileName = DateTime.Now.ToString("yyyyMMddHHmmss_fffff", DateTimeFormatInfo.InvariantInfo) + fileExt; Mac mac = new Mac(options.AttachmentSave_QiNiuKodoAK, options.AttachmentSave_QiNiuKodoSK); byte[] bytes; await using (var ms = new MemoryStream()) { await file.CopyToAsync(ms); bytes = ms.ToArray(); } // 设置上传策略 PutPolicy putPolicy = new PutPolicy(); // 设置要上传的目标空间 putPolicy.Scope = options.AttachmentSave_QiNiuKodoBucketName; // 上传策略的过期时间(单位:秒) putPolicy.SetExpires(3600); // 文件上传完毕后,在多少天后自动被删除 //putPolicy.DeleteAfterDays = 1; // 生成上传token string token = Qiniu.Util.Auth.CreateUploadToken(mac, putPolicy.ToJsonString()); Config config = new Config(); // 设置 http 或者 https 上传 config.UseHttps = true; config.UseCdnDomains = true; config.ChunkSize = ChunkUnit.U512K; UploadManager um = new UploadManager(config); var fileTemp = (options?.AttachmentSavePath?.Substring(1) ?? "") + newFileName; var task = Task.Run(() => um.UploadData(bytes, fileTemp, token, null)); task.Wait(); var outData = task.Result; if (outData?.Code != 200) throw Oops.Oh(outData?.Text); return options.AttachmentSave_QiNiuKodoSaveBaseUrl + options.AttachmentSavePath + newFileName; } #endregion #region 本地上传方法(Base64) /// /// 本地上传方法(Base64) /// /// /// /// public async Task UpLoadBase64ForLocalStorage(SYSDictionaryAttachmentSetting options, MemoryStream memStream) { var newFileName = DateTime.Now.ToString("yyyyMMddHHmmss_ffff", DateTimeFormatInfo.InvariantInfo) + ".jpg"; var today = DateTime.Now.ToString("yyyyMMdd"); byte[] data = new byte[memStream.Length]; memStream.Seek(0, SeekOrigin.Begin); memStream.Read(data, 0, Convert.ToInt32(memStream.Length)); SixLabors.ImageSharp.Image image = SixLabors.ImageSharp.Image.Load(new MemoryStream(data)); var saveUrl = options.AttachmentSavePath + today + "/"; var dirPath = App.WebHostEnvironment.WebRootPath + saveUrl; if (!Directory.Exists(dirPath)) Directory.CreateDirectory(dirPath); var filePath = dirPath + newFileName; var fileUrl = saveUrl + newFileName; //保存到图片 await image.SaveAsync(filePath); return options.AttachmentSave_LogicalSaveBaseUrl + fileUrl; } #endregion #region 阿里云上传方法(Base64) /// /// 阿里云上传方法(Base64) /// /// /// /// public async Task UpLoadBase64ForAliYunOSS(SYSDictionaryAttachmentSetting options, 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 = options.AttachmentSavePath + today + "/" + newFileName; //云文件保存路径 //初始化阿里云配置--外网Endpoint、访问ID、访问password var aliyun = new OssClient(options.AttachmentSave_AliOSSEndpoint, options.AttachmentSave_AliOSSAccessKeyID, options.AttachmentSave_AliOSSAccessKeySecret); //将文件md5值赋值给meat头信息,服务器验证文件MD5 var objectMeta = new ObjectMetadata { ContentMd5 = md5 }; try { //文件上传--空间名、文件保存路径、文件流、meta头信息(文件md5) //返回meta头信息(文件md5) aliyun.PutObject(options.AttachmentSave_AliOSSBucketName, filePath, fileStream, objectMeta); } catch (AggregateException ex) { throw Oops.Oh(ex.Message); } //返回给UEditor的插入编辑器的图片的src return options.AttachmentSave_AliOSSSaveBaseUrl + filePath; } #endregion #region 腾讯云存储上传方法(Base64) /// /// 腾讯云存储上传方法(Base64) /// /// /// /// public async Task UpLoadBase64ForQCloudOSS(SYSDictionaryAttachmentSetting options, byte[] bytes) { var newFileName = DateTime.Now.ToString("yyyyMMddHHmmss_ffff", DateTimeFormatInfo.InvariantInfo) + ".jpg"; var today = DateTime.Now.ToString("yyyyMMdd"); //初始化 CosXmlConfig string appid = options.AttachmentSave_TencentAPPID;//设置腾讯云账户的账户标识 APPID string region = options.AttachmentSave_TencentCosRegion; //设置一个默认的存储桶地域 CosXmlConfig config = new CosXmlConfig.Builder() //.SetAppid(appid) .IsHttps(true) //设置默认 HTTPS 请求 .SetRegion(region) //设置一个默认的存储桶地域 .SetDebugLog(true) //显示日志 .Build(); //创建 CosXmlConfig 对象 long durationSecond = 600; //每次请求签名有效时长,单位为秒 QCloudCredentialProvider qCloudCredentialProvider = new DefaultQCloudCredentialProvider(options.AttachmentSave_TencentSecretId, options.AttachmentSave_TencentSecretKey, durationSecond); var cosXml = new CosXmlServer(config, qCloudCredentialProvider); var filePath = options.AttachmentSavePath + today + "/" + newFileName; //云文件保存路径 try { COSXML.Model.Object.PutObjectRequest putObjectRequest = new COSXML.Model.Object.PutObjectRequest(options.AttachmentSave_TencentBucketName, filePath, bytes); var task = Task.Run(() => cosXml.PutObject(putObjectRequest)); task.Wait(); } catch (COSXML.CosException.CosClientException clientEx) { throw Oops.Oh(clientEx.Message); } catch (COSXML.CosException.CosServerException serverEx) { throw Oops.Oh(serverEx.GetInfo()); } return options.AttachmentSave_TencentSaveBaseUrl + filePath; } #endregion #region 牛云上传方法(Base64) /// /// 七牛云上传方法(Base64) /// /// /// /// public async Task UpLoadBase64ForQiNiuKoDo(SYSDictionaryAttachmentSetting options, byte[] bytes) { var newFileName = DateTime.Now.ToString("yyyyMMddHHmmss_fffff", DateTimeFormatInfo.InvariantInfo) + ".jpg"; Mac mac = new Mac(options.AttachmentSave_QiNiuKodoAK, options.AttachmentSave_QiNiuKodoSK); // 设置上传策略 PutPolicy putPolicy = new PutPolicy(); // 设置要上传的目标空间 putPolicy.Scope = options.AttachmentSave_QiNiuKodoBucketName; // 上传策略的过期时间(单位:秒) putPolicy.SetExpires(3600); // 文件上传完毕后,在多少天后自动被删除 //putPolicy.DeleteAfterDays = 1; // 生成上传token string token = Qiniu.Util.Auth.CreateUploadToken(mac, putPolicy.ToJsonString()); Config config = new Config(); // 设置 http 或者 https 上传 config.UseHttps = true; config.UseCdnDomains = true; config.ChunkSize = ChunkUnit.U512K; var fileTemp = (options?.AttachmentSavePath?.Substring(1) ?? "") + newFileName; UploadManager um = new UploadManager(config); var task = Task.Run(() => um.UploadData(bytes, fileTemp, token, null)); // var outData = um.UploadData(bytes, newFileName, token, null); task.Wait(); var outdata = task.Result; if (outdata?.Code != 200) throw Oops.Oh(outdata?.Text); return options.AttachmentSave_QiNiuKodoSaveBaseUrl + options.AttachmentSavePath + newFileName; } #endregion #region 删除文件 /// /// 删除本地文件 /// /// /// /// public async Task DelFileForLocalStorage(SYSDictionaryAttachmentSetting options, string fileUrl) { string key = App.WebHostEnvironment.WebRootPath + (options.AttachmentSavePath?.RemoveStartWithStr("/") ?? "") + fileUrl.GetFileName(); File.Delete(key); return true; } /// /// 删除七牛文件夹 /// /// /// /// public async Task DelFileForQiNiuKoDo(SYSDictionaryAttachmentSetting options, string fileUrl) { Config config = new Config(); var a = fileUrl.GetFileName(); Mac mac = new Mac(options.AttachmentSave_QiNiuKodoAK, options.AttachmentSave_QiNiuKodoSK); BucketManager bucketManager = new BucketManager(mac, config); string key = (options.AttachmentSavePath?.RemoveStartWithStr("/") ?? "") + fileUrl.GetFileName(); var task = Task.Run(() => bucketManager.Delete(options.AttachmentSave_QiNiuKodoBucketName, key)); // var outData = um.UploadData(bytes, newFileName, token, null); task.Wait(); var outdata = task.Result; if (outdata?.Code != 200) throw Oops.Oh(outdata?.Text); return true; } /// /// 腾讯云删除 /// /// /// 带xxx.xx的链接地址 /// public async Task DelFileForQCloudOSS(SYSDictionaryAttachmentSetting options, string fileUrl) { //初始化 CosXmlConfig string appid = options.AttachmentSave_TencentAPPID;//设置腾讯云账户的账户标识 APPID string region = options.AttachmentSave_TencentCosRegion; //设置一个默认的存储桶地域 CosXmlConfig config = new CosXmlConfig.Builder() //.SetAppid(appid) .IsHttps(true) //设置默认 HTTPS 请求 .SetRegion(region) //设置一个默认的存储桶地域 .SetDebugLog(true) //显示日志 .Build(); //创建 CosXmlConfig 对象 long durationSecond = 600; //每次请求签名有效时长,单位为秒 QCloudCredentialProvider qCloudCredentialProvider = new DefaultQCloudCredentialProvider(options.AttachmentSave_TencentSecretId, options.AttachmentSave_TencentSecretKey, durationSecond); var cosXml = new CosXmlServer(config, qCloudCredentialProvider); string key = (options.AttachmentSavePath?.RemoveStartWithStr("/") ?? "") + fileUrl.GetFileName(); try { COSXML.Model.Object.DeleteObjectRequest DelObjectRequest = new COSXML.Model.Object.DeleteObjectRequest(options.AttachmentSave_TencentBucketName, key); var task = Task.Run(() => cosXml.DeleteObject(DelObjectRequest)); task.Wait(); } catch (COSXML.CosException.CosClientException clientEx) { throw Oops.Oh(clientEx.Message); } catch (COSXML.CosException.CosServerException serverEx) { throw Oops.Oh(serverEx.GetInfo()); } return true; } /// /// 腾讯云删除 /// /// /// 带xxx.xx的链接地址 /// public async Task DelFileForAliYunOSS(SYSDictionaryAttachmentSetting options, string fileUrl) { //初始化阿里云配置--外网Endpoint、访问ID、访问password var aliyun = new OssClient(options.AttachmentSave_AliOSSEndpoint, options.AttachmentSave_AliOSSAccessKeyID, options.AttachmentSave_AliOSSAccessKeySecret); try { var task = Task.Run(() => aliyun.DeleteObject(options.AttachmentSave_AliOSSBucketName, (options.AttachmentSavePath?.RemoveStartWithStr("/") ?? "") + fileUrl.GetFileName())); task.Wait(); } catch (Exception ex) { throw Oops.Oh(ex.Message); } //返回给UEditor的插入编辑器的图片的src return true; } #endregion } }