FileService.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. using System.Threading.Tasks;
  2. using ZhonTai.Admin.Core.Dto;
  3. using ZhonTai.Admin.Services.File.Dto;
  4. using ZhonTai.DynamicApi;
  5. using ZhonTai.DynamicApi.Attributes;
  6. using Microsoft.AspNetCore.Mvc;
  7. using ZhonTai.Admin.Core.Consts;
  8. using ZhonTai.Admin.Domain.File.Dto;
  9. using ZhonTai.Admin.Domain.File;
  10. using Microsoft.AspNetCore.Http;
  11. using System.IO;
  12. using System;
  13. using ZhonTai.Admin.Core.Configs;
  14. using OnceMi.AspNetCore.OSS;
  15. using Microsoft.Extensions.Options;
  16. using System.Linq;
  17. using ZhonTai.Common.Files;
  18. using ZhonTai.Common.Helpers;
  19. using System.ComponentModel.DataAnnotations;
  20. using System.Collections.Generic;
  21. using ZhonTai.Admin.Core.Helpers;
  22. using Microsoft.AspNetCore.Hosting;
  23. namespace ZhonTai.Admin.Services.File;
  24. /// <summary>
  25. /// 文件服务
  26. /// </summary>
  27. [Order(110)]
  28. [DynamicApi(Area = AdminConsts.AreaName)]
  29. public class FileService : BaseService, IFileService, IDynamicApi
  30. {
  31. private IFileRepository _fileRepository => LazyGetRequiredService<IFileRepository>();
  32. private IOSSServiceFactory _oSSServiceFactory => LazyGetRequiredService<IOSSServiceFactory>();
  33. private OSSConfig _oSSConfig => LazyGetRequiredService<IOptions<OSSConfig>>().Value;
  34. private IHttpContextAccessor _httpContextAccessor => LazyGetRequiredService<IHttpContextAccessor>();
  35. public FileService()
  36. {
  37. }
  38. /// <summary>
  39. /// 查询分页
  40. /// </summary>
  41. /// <param name="input"></param>
  42. /// <returns></returns>
  43. [HttpPost]
  44. public async Task<PageOutput<FileGetPageOutput>> GetPageAsync(PageInput<FileGetPageDto> input)
  45. {
  46. var fileName = input.Filter?.FileName;
  47. var list = await _fileRepository.Select
  48. .WhereDynamicFilter(input.DynamicFilter)
  49. .WhereIf(fileName.NotNull(), a => a.FileName.Contains(fileName))
  50. .Count(out var total)
  51. .OrderByDescending(true, c => c.Id)
  52. .Page(input.CurrentPage, input.PageSize)
  53. .ToListAsync(a => new FileGetPageOutput { ProviderName = a.Provider.ToString() });
  54. var data = new PageOutput<FileGetPageOutput>()
  55. {
  56. List = list,
  57. Total = total
  58. };
  59. return data;
  60. }
  61. /// <summary>
  62. /// 删除
  63. /// </summary>
  64. /// <param name="input"></param>
  65. /// <returns></returns>
  66. [HttpPost]
  67. public async Task DeleteAsync(FileDeleteInput input)
  68. {
  69. var file = await _fileRepository.GetAsync(input.Id);
  70. if (file == null)
  71. {
  72. return;
  73. }
  74. var shareFile = await _fileRepository.Where(a=>a.Id != input.Id && a.LinkUrl == file.LinkUrl).AnyAsync();
  75. if (!shareFile)
  76. {
  77. if(file.Provider.HasValue)
  78. {
  79. var oSSService = _oSSServiceFactory.Create(file.Provider.ToString());
  80. var oSSOptions = _oSSConfig.OSSConfigs.Where(a => a.Enable && a.Provider == file.Provider).FirstOrDefault();
  81. var enableOss = oSSOptions != null && oSSOptions.Enable;
  82. if (enableOss)
  83. {
  84. var filePath = Path.Combine(file.FileDirectory, file.SaveFileName + file.Extension).ToPath();
  85. await oSSService.RemoveObjectAsync(file.BucketName, filePath);
  86. }
  87. }
  88. else
  89. {
  90. var env = LazyGetRequiredService<IWebHostEnvironment>();
  91. var filePath = Path.Combine(env.WebRootPath, file.FileDirectory, file.SaveFileName + file.Extension).ToPath();
  92. if (System.IO.File.Exists(filePath))
  93. {
  94. System.IO.File.Delete(filePath);
  95. }
  96. }
  97. }
  98. await _fileRepository.DeleteAsync(file.Id);
  99. }
  100. /// <summary>
  101. /// 上传文件
  102. /// </summary>
  103. /// <param name="file">文件</param>
  104. /// <param name="fileDirectory">文件目录</param>
  105. /// <param name="fileReName">文件重命名</param>
  106. /// <returns></returns>
  107. public async Task<FileEntity> UploadFileAsync([Required] IFormFile file, string fileDirectory = "", bool fileReName = true)
  108. {
  109. var localUploadConfig = _oSSConfig.LocalUploadConfig;
  110. var oSSOptions = _oSSConfig.OSSConfigs.Where(a => a.Enable && a.Provider == _oSSConfig.Provider).FirstOrDefault();
  111. var enableOss = oSSOptions != null && oSSOptions.Enable;
  112. var enableMd5 = enableOss ? oSSOptions.Md5 : localUploadConfig.Md5;
  113. var md5 = string.Empty;
  114. if (enableMd5)
  115. {
  116. md5 = MD5Encrypt.GetHash(file.OpenReadStream());
  117. var md5FileEntity = await _fileRepository.WhereIf(enableOss, a => a.Provider == oSSOptions.Provider).Where(a => a.Md5 == md5).FirstAsync();
  118. if (md5FileEntity != null)
  119. {
  120. var sameFileEntity = new FileEntity
  121. {
  122. Provider = md5FileEntity.Provider,
  123. BucketName = md5FileEntity.BucketName,
  124. FileGuid = FreeUtil.NewMongodbId(),
  125. SaveFileName = md5FileEntity.SaveFileName,
  126. FileName = Path.GetFileNameWithoutExtension(file.FileName),
  127. Extension = Path.GetExtension(file.FileName).ToLower(),
  128. FileDirectory = md5FileEntity.FileDirectory,
  129. Size = md5FileEntity.Size,
  130. SizeFormat = md5FileEntity.SizeFormat,
  131. LinkUrl = md5FileEntity.LinkUrl,
  132. Md5 = md5,
  133. };
  134. sameFileEntity = await _fileRepository.InsertAsync(sameFileEntity);
  135. return sameFileEntity;
  136. }
  137. }
  138. if (fileDirectory.IsNull())
  139. {
  140. fileDirectory = localUploadConfig.Directory;
  141. if (localUploadConfig.DateTimeDirectory.NotNull())
  142. {
  143. fileDirectory = Path.Combine(fileDirectory, DateTime.Now.ToString(localUploadConfig.DateTimeDirectory)).ToPath();
  144. }
  145. }
  146. var fileSize = new FileSize(file.Length);
  147. var fileEntity = new FileEntity
  148. {
  149. Provider = oSSOptions?.Provider,
  150. BucketName = oSSOptions?.BucketName,
  151. FileGuid = FreeUtil.NewMongodbId(),
  152. FileName = Path.GetFileNameWithoutExtension(file.FileName),
  153. Extension = Path.GetExtension(file.FileName).ToLower(),
  154. FileDirectory = fileDirectory,
  155. Size = fileSize.Size,
  156. SizeFormat = fileSize.ToString(),
  157. Md5 = md5
  158. };
  159. fileEntity.SaveFileName = fileReName ? fileEntity.FileGuid.ToString() : fileEntity.FileName;
  160. var filePath = Path.Combine(fileDirectory, fileEntity.SaveFileName + fileEntity.Extension).ToPath();
  161. var url = string.Empty;
  162. if (enableOss)
  163. {
  164. url = oSSOptions.Url;
  165. if (url.IsNull())
  166. {
  167. url = oSSOptions.Provider switch
  168. {
  169. OSSProvider.Minio => $"{oSSOptions.Endpoint}/{oSSOptions.BucketName}",
  170. OSSProvider.Aliyun => $"{oSSOptions.BucketName}.{oSSOptions.Endpoint}",
  171. OSSProvider.QCloud => $"{oSSOptions.BucketName}-{oSSOptions.Endpoint}.cos.{oSSOptions.Region}.myqcloud.com",
  172. OSSProvider.Qiniu => $"{oSSOptions.BucketName}.{oSSOptions.Region}.qiniucs.com",
  173. OSSProvider.HuaweiCloud => $"{oSSOptions.BucketName}.{oSSOptions.Endpoint}",
  174. _ => ""
  175. };
  176. if (url.IsNull())
  177. {
  178. throw ResultOutput.Exception($"请配置{oSSOptions.Provider}的Url参数");
  179. }
  180. var urlProtocol = oSSOptions.IsEnableHttps ? "https" : "http";
  181. fileEntity.LinkUrl = $"{urlProtocol}://{url}/{filePath}";
  182. }
  183. else
  184. {
  185. fileEntity.LinkUrl = $"{url}/{filePath}";
  186. }
  187. }
  188. else
  189. {
  190. fileEntity.LinkUrl = $"{_httpContextAccessor.HttpContext.Request.Scheme}://{_httpContextAccessor.HttpContext.Request.Host.Value}/{filePath}";
  191. }
  192. if (enableOss)
  193. {
  194. var oSSService = _oSSServiceFactory.Create(_oSSConfig.Provider.ToString());
  195. await oSSService.PutObjectAsync(oSSOptions.BucketName, filePath, file.OpenReadStream());
  196. }
  197. else
  198. {
  199. var uploadHelper = LazyGetRequiredService<UploadHelper>();
  200. var env = LazyGetRequiredService<IWebHostEnvironment>();
  201. fileDirectory = Path.Combine(env.WebRootPath, fileDirectory).ToPath();
  202. if (!Directory.Exists(fileDirectory))
  203. {
  204. Directory.CreateDirectory(fileDirectory);
  205. }
  206. filePath = Path.Combine(env.WebRootPath, filePath).ToPath();
  207. await uploadHelper.SaveAsync(file, filePath);
  208. }
  209. fileEntity = await _fileRepository.InsertAsync(fileEntity);
  210. return fileEntity;
  211. }
  212. /// <summary>
  213. /// 上传多文件
  214. /// </summary>
  215. /// <param name="files">文件列表</param>
  216. /// <param name="fileDirectory">文件目录</param>
  217. /// <param name="fileReName">文件重命名</param>
  218. /// <returns></returns>
  219. public async Task<List<FileEntity>> UploadFilesAsync([Required] IFormFileCollection files, string fileDirectory = "", bool fileReName = true)
  220. {
  221. var fileList = new List<FileEntity>();
  222. foreach (var file in files)
  223. {
  224. fileList.Add(await UploadFileAsync(file, fileDirectory, fileReName));
  225. }
  226. return fileList;
  227. }
  228. }