ResourceFileService.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. using Furion.DatabaseAccessor.Extensions;
  2. using Microsoft.Extensions.Options;
  3. using SixLabors.ImageSharp;
  4. using SixLabors.ImageSharp.Processing;
  5. using YBEE.EQM.Core;
  6. namespace YBEE.EQM.Application;
  7. /// <summary>
  8. /// 资源文件管理服务
  9. /// </summary>
  10. public class ResourceFileService(IRepository<ResourceFile> rep, IOptions<EqmSiteOptions> options) : IResourceFileService, ITransient
  11. {
  12. private readonly EqmSiteOptions _eqmSiteOptions = options.Value;
  13. private readonly string[] _thumbImageTypes = [".png", ".jpg", ".jpeg", ".gif", ".bmp"];
  14. /// <summary>
  15. /// 上传文件
  16. /// </summary>
  17. /// <param name="input"></param>
  18. /// <returns></returns>
  19. public async Task<ResourceFileOutput> Upload([FromForm] UploadResourceFileInput input)
  20. {
  21. var savePath = Path.Combine(input.Type.ToString(), input.SourceId.ToString());
  22. var saveRoot = Path.Combine(_eqmSiteOptions.ResourceFileRoot, savePath);
  23. if (!Directory.Exists(saveRoot))
  24. {
  25. Directory.CreateDirectory(saveRoot);
  26. }
  27. var extName = Path.GetExtension(input.File.FileName);
  28. var fileNameGuid = Guid.NewGuid().ToString("N");
  29. var fileName = fileNameGuid + extName;
  30. using var stream = File.Create(Path.Combine(saveRoot, fileName));
  31. await input.File.CopyToAsync(stream);
  32. await stream.FlushAsync();
  33. var reqFileName = !string.IsNullOrEmpty(input.FileName?.Trim());
  34. var saveFileName = reqFileName ? input.FileName : input.File.FileName;
  35. // 生成缩略图
  36. AddResourceFileInput thumbItem = null;
  37. if (_thumbImageTypes.Any(t => t == extName.ToLower()))
  38. {
  39. BinaryReader r = new(stream);
  40. r.BaseStream.Seek(0, SeekOrigin.Begin);
  41. var bs = r.ReadBytes((int)r.BaseStream.Length);
  42. using MemoryStream ms = new(bs);
  43. Image imageFrom = Image.Load(ms);
  44. var thumbFileName = fileNameGuid + "_thumb" + extName;
  45. // 源图宽度及高度
  46. int imageFromWidth = imageFrom.Width;
  47. int imageFromHeight = imageFrom.Height;
  48. int width = 240;
  49. int height = (int)Math.Ceiling(width * (imageFromHeight * 1.0 / imageFromWidth));
  50. if (imageFromHeight > imageFromWidth)
  51. {
  52. height = 240;
  53. width = (int)Math.Ceiling(height * (imageFromWidth * 1.0 / imageFromHeight));
  54. }
  55. var thumbPath = Path.Combine(saveRoot, thumbFileName);
  56. imageFrom.Mutate(x => x.Resize(width, height));
  57. imageFrom.Save(thumbPath);
  58. imageFrom.Dispose();
  59. thumbItem = input.Adapt<AddResourceFileInput>();
  60. thumbItem.FileName = saveFileName.Replace(extName, $"_thumb{extName}");
  61. thumbItem.FilePath = Path.Combine(savePath, thumbFileName);
  62. thumbItem.FileSize = new FileInfo(thumbPath).Length;
  63. thumbItem.FileExtName = extName;
  64. }
  65. AddResourceFileInput item = input.Adapt<AddResourceFileInput>();
  66. item.FileName = saveFileName;
  67. item.FilePath = Path.Combine(savePath, fileName);
  68. item.FileSize = input.File.Length;
  69. item.FileExtName = extName;
  70. return await Add(item, thumbItem);
  71. }
  72. /// <summary>
  73. /// 添加资源文件
  74. /// </summary>
  75. /// <param name="input"></param>
  76. /// <param name="thumbInput">缩略图</param>
  77. /// <returns></returns>
  78. public async Task<ResourceFileOutput> Add(AddResourceFileInput input, AddResourceFileInput thumbInput = null)
  79. {
  80. var item = input.Adapt<ResourceFile>();
  81. await rep.InsertAsync(item);
  82. var ret = item.Adapt<ResourceFileOutput>();
  83. if (thumbInput != null)
  84. {
  85. var thumbItem = thumbInput.Adapt<ResourceFile>();
  86. await rep.InsertAsync(thumbItem);
  87. ret.ThumbResourceFile = thumbItem.Adapt<ResourceFileOutput>();
  88. }
  89. return ret;
  90. }
  91. /// <summary>
  92. /// 删除资源文件
  93. /// </summary>
  94. /// <param name="input"></param>
  95. /// <returns></returns>
  96. public async Task Del(BaseId<long> input)
  97. {
  98. var item = await rep.FirstOrDefaultAsync(t => t.Id == input.Id) ?? throw Oops.Oh(ErrorCode.E2001);
  99. var fpath = Path.Combine(_eqmSiteOptions.ResourceFileRoot, item.FilePath);
  100. if (File.Exists(fpath))
  101. {
  102. File.Delete(fpath);
  103. }
  104. await item.DeleteAsync();
  105. }
  106. /// <summary>
  107. /// 根据ID获取资源详细
  108. /// </summary>
  109. /// <param name="id"></param>
  110. /// <returns></returns>
  111. public async Task<ResourceFileOutput> GetById(long id)
  112. {
  113. var item = await rep.FirstOrDefaultAsync(t => t.Id == id) ?? throw Oops.Oh(ErrorCode.E2001);
  114. return item.Adapt<ResourceFileOutput>();
  115. }
  116. /// <summary>
  117. /// 根据类型和源ID获取资源列表
  118. /// </summary>
  119. /// <param name="type"></param>
  120. /// <param name="sourceId"></param>
  121. /// <returns></returns>
  122. public async Task<List<ResourceFileOutput>> GetListBySourceId(ResourceFileType type, long sourceId)
  123. {
  124. var items = await rep.DetachedEntities.Where(t => t.Type == type && t.SourceId == sourceId).ProjectToType<ResourceFileOutput>().ToListAsync();
  125. return items;
  126. }
  127. }