From bebcf559a16ada6f758f36c9f78320c871f7c4c4 Mon Sep 17 00:00:00 2001 From: "YUN-PC5\\user" Date: Wed, 22 Nov 2023 10:29:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0=E5=8A=A0?= =?UTF-8?q?=E5=AF=86=E5=8F=8A=E5=A2=9E=E5=8A=A0=E6=A0=B9=E6=8D=AE=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E6=96=87=E4=BB=B6=E5=AD=98=E5=82=A8=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E9=80=89=E6=8B=A9=E4=B8=8A=E4=BC=A0=E6=96=B9?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/CommonController.cs | 20 +- .../Controllers/System/SysFileController.cs | 60 ++++- .../System/SysProfileController.cs | 23 +- ZR.Common/AliyunOssHelper.cs | 50 +++++ ZR.Common/Tools.cs | 28 +++ ZR.ServiceCore/Model/SysFile.cs | 15 ++ .../Services/IService/ISysFileService.cs | 35 ++- ZR.ServiceCore/Services/SysFileService.cs | 212 ++++++++++++++++-- 8 files changed, 379 insertions(+), 64 deletions(-) diff --git a/ZR.Admin.WebApi/Controllers/CommonController.cs b/ZR.Admin.WebApi/Controllers/CommonController.cs index 9d621bd..813c2f1 100644 --- a/ZR.Admin.WebApi/Controllers/CommonController.cs +++ b/ZR.Admin.WebApi/Controllers/CommonController.cs @@ -1,15 +1,10 @@ -using System.Net; -using System.Net.Sockets; -using Infrastructure.Helper; +using Infrastructure.Helper; using JinianNet.JNTemplate; -using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Newtonsoft.Json; using ZR.Admin.WebApi.Filters; -using ZR.Model.System; using ZR.Service.IService; using ZR.Service.System; -using ZR.Service.System.IService; using ZR.ServiceCore.Model; using ZR.ServiceCore.Services.IService; @@ -135,15 +130,6 @@ namespace ZR.Admin.WebApi.Controllers SysFile file = new(); string fileExt = Path.GetExtension(formFile.FileName);//文件后缀 double fileSize = Math.Round(formFile.Length / 1024.0, 2);//文件大小KB - var scheme = HttpContext.Request.Scheme + "://"; - var serverIP = HttpContext.Request.Host.Value; - if (WebHostEnvironment.IsProduction()) - { - var host = await Dns.GetHostEntryAsync(Dns.GetHostName()); - var ip = host.AddressList - .FirstOrDefault(it => it.AddressFamily == AddressFamily.InterNetwork); - serverIP = ip + ":" + Request.HttpContext.Connection.LocalPort;//获取服务器IP - } if (OptionsSetting.Upload.NotAllowedExt.Contains(fileExt)) { @@ -166,7 +152,7 @@ namespace ZR.Admin.WebApi.Controllers uploadDto.FileDir = OptionsSetting.Upload.LocalSavePath; } file = await SysFileService.SaveFileToLocal(savePath, uploadDto.FileName, uploadDto.FileDir, - HttpContext.GetUId(), HttpContext.GetName(), formFile, scheme + serverIP); + HttpContext.GetUId(), HttpContext.GetNickName(), formFile, OptionsSetting.Upload.UploadUrl); break; case StoreType.REMOTE: break; @@ -181,7 +167,7 @@ namespace ZR.Admin.WebApi.Controllers return ToResponse(ResultCode.CUSTOM_ERROR, "上传文件过大,不能超过 " + AlimaxContentLength + " MB"); } file = new(formFile.FileName, uploadDto.FileName, fileExt, fileSize + "kb", - uploadDto.FileDir, HttpContext.GetUId(), HttpContext.GetName()) + uploadDto.FileDir, HttpContext.GetUId(), HttpContext.GetNickName()) { StoreType = (int)StoreType.ALIYUN, FileType = formFile.ContentType diff --git a/ZR.Admin.WebApi/Controllers/System/SysFileController.cs b/ZR.Admin.WebApi/Controllers/System/SysFileController.cs index dd22b6f..9476742 100644 --- a/ZR.Admin.WebApi/Controllers/System/SysFileController.cs +++ b/ZR.Admin.WebApi/Controllers/System/SysFileController.cs @@ -1,8 +1,5 @@ -using Microsoft.AspNetCore.Mvc; using SqlSugar; using ZR.Admin.WebApi.Filters; -using ZR.Model.System; -using ZR.Service.System.IService; using ZR.ServiceCore.Model; using ZR.ServiceCore.Model.Dto; using ZR.ServiceCore.Services.IService; @@ -20,11 +17,11 @@ namespace ZR.Admin.WebApi.Controllers /// /// 文件存储接口 /// - private readonly ISysFileService _SysFileService; + private readonly ISysFileService _sysFileService; - public SysFileController(ISysFileService SysFileService) + public SysFileController(ISysFileService sysFileService) { - _SysFileService = SysFileService; + _sysFileService = sysFileService; } /// @@ -43,7 +40,7 @@ namespace ZR.Admin.WebApi.Controllers predicate = predicate.AndIF(parm.StoreType != null, m => m.StoreType == parm.StoreType); predicate = predicate.AndIF(parm.FileId != null, m => m.Id == parm.FileId); - var response = _SysFileService.GetPages(predicate.ToExpression(), parm, x => x.Id, OrderByType.Desc); + var response = _sysFileService.GetPages(predicate.ToExpression(), parm, x => x.Id, OrderByType.Desc); return SUCCESS(response); } @@ -56,7 +53,7 @@ namespace ZR.Admin.WebApi.Controllers [ActionPermissionFilter(Permission = "tool:file:query")] public IActionResult GetSysFile(long Id) { - var response = _SysFileService.GetFirst(x => x.Id == Id); + var response = _sysFileService.GetFirst(x => x.Id == Id); return SUCCESS(response); } @@ -68,13 +65,12 @@ namespace ZR.Admin.WebApi.Controllers [HttpDelete("{ids}")] [ActionPermissionFilter(Permission = "tool:file:delete")] [Log(Title = "文件存储", BusinessType = BusinessType.DELETE)] - public IActionResult DeleteSysFile(string ids) + public async Task DeleteSysFile(string ids) { long[] idsArr = Tools.SpitLongArrary(ids); if (idsArr.Length <= 0) { return ToResponse(ApiResult.Error($"删除失败Id 不能为空")); } - var response = _SysFileService.Delete(idsArr); - //TODO 删除本地资源 + var response = await _sysFileService.DeleteSysFileAsync(idsArr); return ToResponse(response); } @@ -88,10 +84,50 @@ namespace ZR.Admin.WebApi.Controllers [ActionPermissionFilter(Permission = "tool:file:export")] public IActionResult Export() { - var list = _SysFileService.GetAll(); + var list = _sysFileService.GetAll(); string sFileName = ExportExcel(list, "SysFile", "文件存储"); return SUCCESS(new { path = "/export/" + sFileName, fileName = sFileName }); } + + /// + /// 通过文件ID下载文件 + /// + /// + /// + [HttpPost("download")] + public IActionResult Download([FromBody] SysFile file) + { + var sysFile = _sysFileService.Queryable().Where(it => it.Id == file.Id).First(); + if (sysFile == null) + { + return NoContent(); + } + + Stream? stream = null; + switch ((StoreType)Enum.Parse(typeof(StoreType), sysFile.StoreType.ToString() ?? string.Empty)) + { + case StoreType.LOCAL: + stream = sysFile.IsEncrypted == "1" ? _sysFileService.DecryptSysFileStream(sysFile.FileUrl) + : new FileStream(sysFile.FileUrl, FileMode.Open); + break; + case StoreType.ALIYUN: + stream = AliyunOssHelper.DownloadFile(sysFile.FileUrl, "", sysFile.IsEncrypted == "1"); + break; + default: + throw new CustomException("不支持的存储类型"); + } + if (stream != null) + { + return new FileStreamResult(stream, "application/octet-stream") + { + FileDownloadName = sysFile.RealName + }; + } + else + { + return NoContent(); + } + } } } \ No newline at end of file diff --git a/ZR.Admin.WebApi/Controllers/System/SysProfileController.cs b/ZR.Admin.WebApi/Controllers/System/SysProfileController.cs index 252d985..ff7008a 100644 --- a/ZR.Admin.WebApi/Controllers/System/SysProfileController.cs +++ b/ZR.Admin.WebApi/Controllers/System/SysProfileController.cs @@ -1,8 +1,5 @@ -using System.Net; -using System.Net.Sockets; -using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; using ZR.Admin.WebApi.Filters; -using ZR.Model.System; using ZR.Service.System.IService; using ZR.ServiceCore.Model; using ZR.ServiceCore.Model.Dto; @@ -24,6 +21,7 @@ namespace ZR.Admin.WebApi.Controllers.System private readonly ISysDeptService DeptService; private readonly ISysFileService FileService; private IWebHostEnvironment hostEnvironment; + private readonly OptionsSetting _optionsSetting; public SysProfileController( ISysUserService userService, @@ -31,7 +29,8 @@ namespace ZR.Admin.WebApi.Controllers.System ISysUserPostService postService, ISysDeptService deptService, ISysFileService sysFileService, - IWebHostEnvironment hostEnvironment) + IWebHostEnvironment hostEnvironment, + IOptions options) { UserService = userService; RoleService = roleService; @@ -39,6 +38,7 @@ namespace ZR.Admin.WebApi.Controllers.System DeptService = deptService; FileService = sysFileService; this.hostEnvironment = hostEnvironment; + _optionsSetting = options.Value; } /// @@ -122,19 +122,10 @@ namespace ZR.Admin.WebApi.Controllers.System { long userId = HttpContext.GetUId(); if (formFile == null) throw new CustomException("请选择文件"); - - var scheme = HttpContext.Request.Scheme + "://"; - var serverIP = HttpContext.Request.Host.Value; - if (hostEnvironment.IsProduction()) - { - var host = await Dns.GetHostEntryAsync(Dns.GetHostName()); - var ip = host.AddressList - .FirstOrDefault(it => it.AddressFamily == AddressFamily.InterNetwork); - serverIP = ip + ":" + Request.HttpContext.Connection.LocalPort;//获取服务器IP - } + var file = await FileService.SaveFileToLocal(hostEnvironment.WebRootPath, "", "avatar", - HttpContext.GetUId(), HttpContext.GetName(), formFile, serverIP); + HttpContext.GetUId(), HttpContext.GetName(), formFile, _optionsSetting.Upload.UploadUrl); UserService.UpdatePhoto(new SysUser() { Avatar = file.AccessUrl, UserId = userId }); return SUCCESS(new { imgUrl = file.AccessUrl }); diff --git a/ZR.Common/AliyunOssHelper.cs b/ZR.Common/AliyunOssHelper.cs index b45c87a..0360e6f 100644 --- a/ZR.Common/AliyunOssHelper.cs +++ b/ZR.Common/AliyunOssHelper.cs @@ -3,6 +3,7 @@ using Aliyun.OSS.Common; using Infrastructure; using System; using System.IO; +using System.Security.Cryptography; namespace ZR.Common { @@ -55,7 +56,9 @@ namespace ZR.Common try { OssClient client = new(endpoint, accessKeyId, accessKeySecret); + dirPath = dirPath.Replace("\\", "/"); DeleteObjectResult putObjectResult = client.DeleteObject(bucketName, dirPath); + return putObjectResult.HttpStatusCode; } catch (Exception ex) { @@ -63,5 +66,52 @@ namespace ZR.Common } return System.Net.HttpStatusCode.BadRequest; } + + public static Stream DownloadFile(string dirPath, string bucketName = "", bool isEncrypted = false) + { + if (string.IsNullOrEmpty(bucketName)) + { + bucketName = bucketName1; + } + try + { + OssClient client = new(endpoint, accessKeyId, accessKeySecret); + dirPath = dirPath.Replace("\\", "/"); + var ossObject = client.GetObject(bucketName, dirPath); + if (isEncrypted) + { + try + { + var key = new byte[] + { + 13, 57, 174, 2, 102, 26, 253, 192, 141, 38, 175, 244, 32, 86, 163, 25, 237, 134, + 253, 162, 62, 203, 57, 52, 56, 157, 78, 155, 63, 28, 63, 255 + }; + var iv = new byte[] + { + 137, 221, 84, 122, 104, 162, 48, 60, 108, 130, 170, 238, 186, 190, 111, 176 + }; + var aes = Aes.Create(); + aes.Key = key; + aes.IV = iv; + var decryptor = aes.CreateDecryptor(); + var cryptoStream = new CryptoStream(ossObject.Content, decryptor, CryptoStreamMode.Read); + return cryptoStream; + } + catch (Exception e) + { + // 处理异常,例如记录日志或抛出自定义异常 + Console.WriteLine($"解密文件时发生异常: {e.Message}"); + throw; + } + } + return ossObject.Content; + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + } } } diff --git a/ZR.Common/Tools.cs b/ZR.Common/Tools.cs index d95c47f..7ee02d9 100644 --- a/ZR.Common/Tools.cs +++ b/ZR.Common/Tools.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.IO; +using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; @@ -126,5 +128,31 @@ namespace ZR.Common return true; //由数字、字母、符号构成的密码 } + + /// + /// 获取文件的MD5值 + /// + /// 文件流 + /// + public static string GetMD5HashFromFile(Stream filestream) + { + try + { + MD5 md5 = new MD5CryptoServiceProvider(); + byte[] retVal = md5.ComputeHash(filestream); + filestream.Close(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < retVal.Length; i++) + { + sb.Append(retVal[i].ToString("x2")); + } + return sb.ToString(); + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + } } } diff --git a/ZR.ServiceCore/Model/SysFile.cs b/ZR.ServiceCore/Model/SysFile.cs index 8144663..c77d371 100644 --- a/ZR.ServiceCore/Model/SysFile.cs +++ b/ZR.ServiceCore/Model/SysFile.cs @@ -58,6 +58,21 @@ /// 访问路径 /// public string AccessUrl { get; set; } + /// + /// 描述 : 文件MD5 + /// 空值 : true + /// + public string FileMd5 { get; set; } + /// + /// 已加密 + /// + public string IsEncrypted { get; set; } + /// + /// 描述:文件是否已上传 + /// 空值:false + /// + [SugarColumn(IsIgnore = true)] + public bool FileExists { get; set; } public SysFile() { } public SysFile(string originFileName, string fileName, string ext, string fileSize, string storePath, diff --git a/ZR.ServiceCore/Services/IService/ISysFileService.cs b/ZR.ServiceCore/Services/IService/ISysFileService.cs index 7fc4de9..8876b71 100644 --- a/ZR.ServiceCore/Services/IService/ISysFileService.cs +++ b/ZR.ServiceCore/Services/IService/ISysFileService.cs @@ -8,16 +8,20 @@ namespace ZR.ServiceCore.Services.IService { Task InsertFile(SysFile file); + Task SaveFile(SysFile file, IFormFile formFile, string rootPath, string uploadUrl); + /// /// 上传文件 /// - /// - /// - /// /// - /// + /// + /// + /// + /// + /// + /// /// 文件对象 - Task SaveFileToLocal(string rootPath, string fileName, string fileDir, long userId, string userName, + Task SaveFileToLocal(string rootPath, string fileName, string fileDir, long userId, string nickName, IFormFile formFile, string uploadUrl); Task SaveFileToAliyun(SysFile file, IFormFile formFile); @@ -35,5 +39,26 @@ namespace ZR.ServiceCore.Services.IService /// 文件名,不包括扩展名 /// string HashFileName(string str = null); + + /// + /// 删除文件 + /// + /// 文件ID + /// + Task DeleteSysFileAsync(long[] ids); + + /// + /// 条件查询文件列表 + /// + /// 文件对象 + /// + List SelectFileList(SysFile sysFile); + + /// + /// 文件解密流 + /// + /// + /// + Stream DecryptSysFileStream(string fileUrl); } } diff --git a/ZR.ServiceCore/Services/SysFileService.cs b/ZR.ServiceCore/Services/SysFileService.cs index 90a5330..75fbf01 100644 --- a/ZR.ServiceCore/Services/SysFileService.cs +++ b/ZR.ServiceCore/Services/SysFileService.cs @@ -22,25 +22,42 @@ namespace ZR.ServiceCore.Services public class SysFileService : BaseService, ISysFileService { private string domainUrl = AppSettings.GetConfig("ALIYUN_OSS:domainUrl"); - private readonly ISysConfigService SysConfigService; - private OptionsSetting OptionsSetting; + private readonly ISysConfigService _sysConfigService; + private OptionsSetting _optionsSetting; public SysFileService(ISysConfigService sysConfigService, IOptions options) { - SysConfigService = sysConfigService; - OptionsSetting = options.Value; + _sysConfigService = sysConfigService; + _optionsSetting = options.Value; + } + + public async Task SaveFile(SysFile file, IFormFile formFile, string rootPath, string uploadUrl) + { + var storeTypeConfig = _sysConfigService.GetSysConfigByKey("sys.file.storetype").ConfigValue; + switch ((StoreType)Enum.Parse(typeof(StoreType), storeTypeConfig)) + { + case StoreType.LOCAL: + return await SaveFileToLocal(rootPath, file.FileName, + file.StorePath, file.Create_by, file.Create_name, formFile, uploadUrl); + case StoreType.ALIYUN: + return await SaveFileToAliyun(file, formFile); + default: + throw new ArgumentOutOfRangeException(); + } } /// /// 存储本地 /// - /// 存储文件夹 /// 存储根目录 /// 自定文件名 + /// 存储文件夹 + /// + /// /// 上传的文件流 - /// + /// /// - public async Task SaveFileToLocal(string rootPath, string fileName, string fileDir, long userId, string userName, - IFormFile formFile, string uploadUrl) + public async Task SaveFileToLocal(string rootPath, string fileName, string fileDir, long userId, + string nickName, IFormFile formFile, string uploadUrl) { string fileExt = Path.GetExtension(formFile.FileName); fileName = (fileName.IsEmpty() ? HashFileName() : fileName) + fileExt; @@ -53,20 +70,56 @@ namespace ZR.ServiceCore.Services { Directory.CreateDirectory(Path.GetDirectoryName(finalFilePath)); } - - using (var stream = new FileStream(finalFilePath, FileMode.Create)) + + var md5HashFromFile = Tools.GetMD5HashFromFile(formFile.OpenReadStream()); + var exp = Expressionable.Create(); + exp.AndIF(md5HashFromFile.IsNotEmpty(), it => it.FileMd5 == md5HashFromFile); + var sysFile = await GetSingleAsync(exp.ToExpression()); + if (sysFile != null) { + sysFile.FileExists = true; + return sysFile; + } + + var notEncryptExt = _sysConfigService.GetSysConfigByKey("sys.file.notEncryptExt") + .ConfigValue.Split(","); + var encryptOnOff = !notEncryptExt.Contains(fileExt) && _sysConfigService + .GetSysConfigByKey("sys.file.encryptOnOff").ConfigValue.ParseToBool(); + if (encryptOnOff) + { + var key = new byte[] + { + 13, 57, 174, 2, 102, 26, 253, 192, 141, 38, 175, 244, 32, 86, 163, 25, 237, 134, + 253, 162, 62, 203, 57, 52, 56, 157, 78, 155, 63, 28, 63, 255 + }; + var iv = new byte[] + { + 137, 221, 84, 122, 104, 162, 48, 60, 108, 130, 170, 238, 186, 190, 111, 176 + }; + + var encryptor = Aes.Create().CreateEncryptor(key, iv); + await using var outputFileStream = new FileStream(finalFilePath, FileMode.Create); + await using var cryptoStream = new CryptoStream(outputFileStream, encryptor, CryptoStreamMode.Write); + await formFile.CopyToAsync(cryptoStream); + } + else + { + await using var stream = new FileStream(finalFilePath, FileMode.Create); await formFile.CopyToAsync(stream); } + // string uploadUrl = OptionsSetting.Upload.UploadUrl; string accessPath = string.Concat(uploadUrl, "/", filePath.Replace("\\", "/"), "/", fileName); - SysFile file = new(formFile.FileName, fileName, fileExt, fileSize + "kb", filePath, userId, userName) + SysFile file = new(formFile.FileName, fileName, fileExt, fileSize + "kb", filePath, userId, nickName) { StoreType = (int)StoreType.LOCAL, FileType = formFile.ContentType, FileUrl = finalFilePath.Replace("\\", "/"), AccessUrl = accessPath }; + file.IsEncrypted = encryptOnOff ? "1" : "0"; + file.FileExists = false; + file.FileMd5 = md5HashFromFile; file.Id = await InsertFile(file); return file; } @@ -82,12 +135,49 @@ namespace ZR.ServiceCore.Services file.FileName = (file.FileName.IsEmpty() ? HashFileName() : file.FileName) + file.FileExt; file.StorePath = GetdirPath(file.StorePath); string finalPath = Path.Combine(file.StorePath, file.FileName); - HttpStatusCode statusCode = AliyunOssHelper.PutObjectFromFile(formFile.OpenReadStream(), finalPath, ""); - if (statusCode != HttpStatusCode.OK) return file; + + var md5HashFromFile = Tools.GetMD5HashFromFile(formFile.OpenReadStream()); + var exp = Expressionable.Create(); + exp.AndIF(md5HashFromFile.IsNotEmpty(), it => it.FileMd5 == md5HashFromFile); + var sysFile = await GetSingleAsync(exp.ToExpression()); + if (sysFile != null) + { + sysFile.FileExists = true; + return sysFile; + } + var notEncryptExt = _sysConfigService.GetSysConfigByKey("sys.file.notEncryptExt") + .ConfigValue.Split(","); + var encryptOnOff = !notEncryptExt.Contains(file.FileExt) && _sysConfigService.GetSysConfigByKey("sys.file.encryptOnOff") + .ConfigValue.ParseToBool(); + if (encryptOnOff) + { + var key = new byte[] + { + 13, 57, 174, 2, 102, 26, 253, 192, 141, 38, 175, 244, 32, 86, 163, 25, 237, 134, + 253, 162, 62, 203, 57, 52, 56, 157, 78, 155, 63, 28, 63, 255 + }; + var iv = new byte[] + { + 137, 221, 84, 122, 104, 162, 48, 60, 108, 130, 170, 238, 186, 190, 111, 176 + }; + var encryptor = Aes.Create().CreateEncryptor(key, iv); + await using var cryptoStream = new CryptoStream(formFile.OpenReadStream(), encryptor, CryptoStreamMode.Write); + HttpStatusCode statusCode = AliyunOssHelper.PutObjectFromFile(cryptoStream, finalPath, ""); + if (statusCode != HttpStatusCode.OK) return file; + + } + else + { + HttpStatusCode statusCode = AliyunOssHelper.PutObjectFromFile(formFile.OpenReadStream(), finalPath, ""); + if (statusCode != HttpStatusCode.OK) return file; + } - file.StorePath = file.StorePath; + file.IsEncrypted = encryptOnOff ? "1" : "0"; + file.FileExists = false; + file.FileMd5 = md5HashFromFile; file.FileUrl = finalPath; file.AccessUrl = string.Concat(domainUrl, "/", file.StorePath.Replace("\\", "/"), "/", file.FileName); + file.StoreType = (int)StoreType.ALIYUN; file.Id = await InsertFile(file); return file; @@ -120,6 +210,52 @@ namespace ZR.ServiceCore.Services return BitConverter.ToString(MD5.HashData(Encoding.Default.GetBytes(str)), 4, 8).Replace("-", ""); } + public async Task DeleteSysFileAsync(long[] ids) + { + var sysFiles = await GetListAsync(x => ids.Contains(x.Id)); + // var accessUrls = sysFiles.Select(t => t.AccessUrl).ToList(); + var res = 0; + foreach (var item in sysFiles) + { + switch (item.StoreType) + { + case (int)StoreType.LOCAL: + File.Delete(item.FileUrl); + res += await DeleteByIdAsync(item.Id) ? 1 : 0; + break; + case (int)StoreType.ALIYUN: + var httpStatusCode = AliyunOssHelper.DeleteFile(item.FileUrl); + if (httpStatusCode == HttpStatusCode.NoContent) + { + res += await DeleteByIdAsync(item.Id) ? 1 : 0; + } + + break; + } + } + + return res; + } + + public List SelectFileList(SysFile sysFile) + { + var exp = Expressionable.Create(); + exp.AndIF(sysFile.FileName.IsNotEmpty(), it => it.FileName.Contains(sysFile.FileName)); + exp.AndIF(sysFile.FileExt.IsNotEmpty(), it => it.FileExt == sysFile.FileExt); + exp.AndIF(sysFile.FileSize.IsNotEmpty(), it => it.FileSize == sysFile.FileSize); + exp.AndIF(sysFile.StorePath.IsNotEmpty(), it => it.StorePath == sysFile.StorePath); + exp.AndIF(sysFile.StoreType > 0, it => it.StoreType == sysFile.StoreType); + exp.AndIF(sysFile.FileType.IsNotEmpty(), it => it.FileType == sysFile.FileType); + exp.AndIF(sysFile.AccessUrl.IsNotEmpty(), it => it.AccessUrl == sysFile.AccessUrl); + exp.AndIF(sysFile.FileUrl.IsNotEmpty(), it => it.FileUrl == sysFile.FileUrl); + exp.AndIF(sysFile.Create_by.IsNotEmpty(), it => it.Create_by == sysFile.Create_by); + exp.AndIF(sysFile.Create_name.IsNotEmpty(), it => it.Create_name == sysFile.Create_name); + exp.AndIF(sysFile.Create_time != null, it => it.Create_time == sysFile.Create_time); + exp.AndIF(sysFile.FileMd5.IsNotEmpty(), it => it.FileMd5 == sysFile.FileMd5); + exp.AndIF(sysFile.Id > 0, it => it.Id == sysFile.Id); + return GetList(exp.ToExpression()); + } + public Task InsertFile(SysFile file) { try @@ -132,5 +268,53 @@ namespace ZR.ServiceCore.Services throw new Exception(ex.Message); } } + + /// + /// 文件解密流 + /// + /// + /// + public Stream DecryptSysFileStream(string fileUrl) + { + var key = new byte[] + { + 13, 57, 174, 2, 102, 26, 253, 192, 141, 38, 175, 244, 32, 86, 163, 25, 237, 134, + 253, 162, 62, 203, 57, 52, 56, 157, 78, 155, 63, 28, 63, 255 + }; + var iv = new byte[] + { + 137, 221, 84, 122, 104, 162, 48, 60, 108, 130, 170, 238, 186, 190, 111, 176 + }; + try + { + var aes = Aes.Create(); + aes.Key = key; + aes.IV = iv; + var decryptor = aes.CreateDecryptor(); + var fsInput = new FileStream(fileUrl.Replace("/","\\"), FileMode.Open, FileAccess.ReadWrite); + var msOutput = new MemoryStream(); + var cryptoStream = new CryptoStream(fsInput, decryptor, CryptoStreamMode.Read); + // 从加密文件中读取并解密 + int bytesRead; + var buffer = new byte[4096]; + while ((bytesRead = cryptoStream.Read(buffer, 0, buffer.Length)) > 0) + { + msOutput.Write(buffer, 0, bytesRead); + } + + fsInput.Position = 0; + cryptoStream.Close(); + // 返回解密后的流 + msOutput.Position = 0; + return msOutput; + } + catch (Exception e) + { + // 处理异常,例如记录日志或抛出自定义异常 + Console.WriteLine($"解密文件时发生异常: {e.Message}"); + throw; + } + + } } }