SysFileService.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. using Furion;
  2. using Furion.DependencyInjection;
  3. using Furion.DynamicApiController;
  4. using Furion.FriendlyException;
  5. using Furion.RemoteRequest.Extensions;
  6. using Microsoft.AspNetCore.Authorization;
  7. using Microsoft.AspNetCore.Http;
  8. using Microsoft.AspNetCore.Mvc;
  9. using Microsoft.Extensions.Options;
  10. using OnceMi.AspNetCore.OSS;
  11. using System;
  12. using System.Collections.Generic;
  13. using System.ComponentModel.DataAnnotations;
  14. using System.IO;
  15. using System.Linq;
  16. using System.Text;
  17. using System.Text.RegularExpressions;
  18. using System.Threading.Tasks;
  19. using System.Web;
  20. namespace Admin.NET.Core.Service
  21. {
  22. /// <summary>
  23. /// 文件服务
  24. /// </summary>
  25. [ApiDescriptionSettings(Name = "文件服务", Order = 194)]
  26. public class SysFileService : IDynamicApiController, ITransient
  27. {
  28. private readonly SqlSugarRepository<SysFile> _sysFileRep;
  29. private readonly OSSProviderOptions _OSSProviderOptions;
  30. private readonly IOSSService _OSSService;
  31. private readonly UploadOptions _uploadOptions;
  32. private readonly ICommonService _commonService;
  33. public SysFileService(SqlSugarRepository<SysFile> sysFileRep,
  34. IOptions<OSSProviderOptions> oSSProviderOptions,
  35. IOSSServiceFactory ossServiceFactory,
  36. ICommonService commonService,
  37. IOptions<UploadOptions> uploadOptions)
  38. {
  39. _sysFileRep = sysFileRep;
  40. _OSSProviderOptions = oSSProviderOptions.Value;
  41. _commonService = commonService;
  42. if (_OSSProviderOptions.IsEnable)
  43. _OSSService = ossServiceFactory.Create(_OSSProviderOptions.Provider.ToString());
  44. _uploadOptions = uploadOptions.Value;
  45. }
  46. /// <summary>
  47. /// 获取文件分页列表
  48. /// </summary>
  49. /// <param name="input"></param>
  50. /// <returns></returns>
  51. [HttpGet("/sysFile/pageList")]
  52. public async Task<SqlSugarPagedList<SysFile>> QueryFilePageList([FromQuery] PageFileInput input)
  53. {
  54. var files = await _sysFileRep.AsQueryable()
  55. .WhereIF(!string.IsNullOrWhiteSpace(input.FileName), u => u.FileName.Contains(input.FileName.Trim()))
  56. .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()) && !string.IsNullOrWhiteSpace(input.EndTime.ToString()),
  57. u => u.CreateTime >= input.StartTime && u.CreateTime <= input.EndTime)
  58. .OrderBy(u => u.CreateTime, SqlSugar.OrderByType.Desc)
  59. .ToPagedListAsync(input.Page, input.PageSize);
  60. return files;
  61. }
  62. /// <summary>
  63. /// 获取文件列表
  64. /// </summary>
  65. /// <returns></returns>
  66. [HttpGet("/sysFile/list")]
  67. public async Task<List<SysFile>> GetFileList()
  68. {
  69. return await _sysFileRep.GetListAsync();
  70. }
  71. /// <summary>
  72. /// 上传文件
  73. /// </summary>
  74. /// <param name="file"></param>
  75. /// <returns></returns>
  76. [HttpPost("/sysFile/upload")]
  77. [AllowAnonymous]
  78. public async Task<FileOutput> UploadFile([Required] IFormFile file)
  79. {
  80. var sysFile = await HandleUploadFile(file);
  81. return new FileOutput
  82. {
  83. Id = sysFile.Id,
  84. Url = _commonService.GetFileUrl(sysFile),
  85. SizeKb = sysFile.SizeKb,
  86. Suffix = sysFile.Suffix,
  87. FilePath = sysFile.FilePath,
  88. };
  89. }
  90. /// <summary>
  91. /// 下载文件(文件流)
  92. /// </summary>
  93. /// <param name="input"></param>
  94. /// <returns></returns>
  95. [HttpPost("/sysFile/download")]
  96. public async Task<IActionResult> DownloadFile(FileInput input)
  97. {
  98. var file = await GetFile(input);
  99. var fileName = HttpUtility.UrlEncode(file.FileName, Encoding.GetEncoding("UTF-8"));
  100. if (_OSSProviderOptions.IsEnable)
  101. {
  102. var filePath = string.Concat(file.FilePath, "/", input.Id.ToString() + file.Suffix);
  103. var stream = await (await _OSSService.PresignedGetObjectAsync(file.BucketName.ToString(), filePath, 5)).GetAsStreamAsync();
  104. return new FileStreamResult(stream, "application/octet-stream") { FileDownloadName = fileName };
  105. }
  106. else
  107. {
  108. var filePath = Path.Combine(file.FilePath, input.Id.ToString() + file.Suffix);
  109. var path = Path.Combine(App.WebHostEnvironment.WebRootPath, filePath);
  110. return new FileStreamResult(new FileStream(path, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };
  111. }
  112. }
  113. /// <summary>
  114. /// 删除文件
  115. /// </summary>
  116. /// <param name="input"></param>
  117. /// <returns></returns>
  118. [HttpPost("/sysFile/delete")]
  119. public async Task DeleteFile(DeleteFileInput input)
  120. {
  121. var file = await _sysFileRep.GetFirstAsync(u => u.Id == input.Id);
  122. if (file != null)
  123. {
  124. await _sysFileRep.DeleteAsync(file);
  125. if (_OSSProviderOptions.IsEnable)
  126. {
  127. await _OSSService.RemoveObjectAsync(file.BucketName.ToString(), string.Concat(file.FilePath, "/", input.Id.ToString()));
  128. }
  129. else
  130. {
  131. var filePath = Path.Combine(App.WebHostEnvironment.WebRootPath, file.FilePath, input.Id.ToString() + file.Suffix);
  132. if (File.Exists(filePath))
  133. File.Delete(filePath);
  134. }
  135. }
  136. }
  137. /// <summary>
  138. /// 获取文件
  139. /// </summary>
  140. /// <param name="input"></param>
  141. /// <returns></returns>
  142. private async Task<SysFile> GetFile([FromQuery] FileInput input)
  143. {
  144. var file = await _sysFileRep.GetFirstAsync(u => u.Id == input.Id);
  145. return file ?? throw Oops.Oh(ErrorCodeEnum.D8000);
  146. }
  147. /// <summary>
  148. /// 上传文件
  149. /// </summary>
  150. /// <param name="file">文件</param>
  151. /// <returns></returns>
  152. private async Task<SysFile> HandleUploadFile(IFormFile file)
  153. {
  154. if (file == null) throw Oops.Oh(ErrorCodeEnum.D8000);
  155. var path = _uploadOptions.Path;
  156. Regex reg = new Regex(@"(\{.+?})");
  157. var match = reg.Matches(path);
  158. match.ToList().ForEach(a =>
  159. {
  160. var str = DateTime.Now.ToString(a.ToString().Substring(1, a.Length - 2));
  161. path = path.Replace(a.ToString(), str);
  162. });
  163. if (!_uploadOptions.ContentType.Contains(file.ContentType))
  164. throw Oops.Oh(ErrorCodeEnum.D8001);
  165. var sizeKb = (long)(file.Length / 1024.0); // 大小KB
  166. if (sizeKb > _uploadOptions.MaxSize) throw Oops.Oh(ErrorCodeEnum.D8002);
  167. var suffix = Path.GetExtension(file.FileName).ToLower(); // 后缀
  168. // 先存库获取Id
  169. var newFile = await _sysFileRep.AsInsertable(new SysFile
  170. {
  171. BucketName = _OSSProviderOptions.IsEnable ? _OSSProviderOptions.Provider.ToString() : "Local",
  172. FileName = Path.GetFileNameWithoutExtension(file.FileName),
  173. Suffix = suffix,
  174. SizeKb = sizeKb.ToString(),
  175. FilePath = path
  176. }).ExecuteReturnEntityAsync();
  177. var finalName = newFile.Id + suffix; // 文件最终名称
  178. if (_OSSProviderOptions.IsEnable)
  179. {
  180. var filePath = string.Concat(path, "/", finalName);
  181. await _OSSService.PutObjectAsync(newFile.BucketName.ToString(), filePath, file.OpenReadStream());
  182. }
  183. else
  184. {
  185. var filePath = Path.Combine(App.WebHostEnvironment.WebRootPath, path);
  186. if (!Directory.Exists(filePath))
  187. Directory.CreateDirectory(filePath);
  188. using var stream = File.Create(Path.Combine(filePath, finalName));
  189. await file.CopyToAsync(stream);
  190. }
  191. return newFile;
  192. }
  193. }
  194. }