using Furion.DatabaseAccessor.Extensions; using Microsoft.Extensions.Options; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Processing; using YBEE.EQM.Core; namespace YBEE.EQM.Application; /// /// 资源文件管理服务 /// public class ResourceFileService : IResourceFileService, ITransient { private readonly IRepository _rep; private readonly EqmSiteOptions _eqmSiteOptions; private readonly string[] _thumbImageTypes = { ".png", ".jpg", "jpeg", ".gif", ".bmp" }; public ResourceFileService(IRepository rep, IOptions options) { _rep = rep; _eqmSiteOptions = options.Value; } /// /// 上传文件 /// /// /// public async Task Upload([FromForm] UploadResourceFileInput input) { var savePath = Path.Combine(input.Type.ToString(), input.SourceId.ToString()); var saveRoot = Path.Combine(_eqmSiteOptions.ResourceFileRoot, savePath); if (!Directory.Exists(saveRoot)) { Directory.CreateDirectory(saveRoot); } var extName = Path.GetExtension(input.File.FileName); var fileNameGuid = Guid.NewGuid().ToString("N"); var fileName = fileNameGuid + extName; using var stream = File.Create(Path.Combine(saveRoot, fileName)); await input.File.CopyToAsync(stream); await stream.FlushAsync(); var reqFileName = !string.IsNullOrEmpty(input.FileName?.Trim()); var saveFileName = reqFileName ? input.FileName : input.File.FileName; // 生成缩略图 AddResourceFileInput thumbItem = null; if (_thumbImageTypes.Any(t => t == extName.ToLower())) { BinaryReader r = new(stream); r.BaseStream.Seek(0, SeekOrigin.Begin); var bs = r.ReadBytes((int)r.BaseStream.Length); using MemoryStream ms = new(bs); Image imageFrom = Image.Load(ms); var thumbFileName = fileNameGuid + "_thumb" + extName; // 源图宽度及高度 int imageFromWidth = imageFrom.Width; int imageFromHeight = imageFrom.Height; int width = 240; int height = (int)Math.Ceiling(width * (imageFromHeight * 1.0 / imageFromWidth)); if (imageFromHeight > imageFromWidth) { height = 240; width = (int)Math.Ceiling(height * (imageFromWidth * 1.0 / imageFromHeight)); } var thumbPath = Path.Combine(saveRoot, thumbFileName); imageFrom.Mutate(x => x.Resize(width, height)); imageFrom.Save(thumbPath); imageFrom.Dispose(); thumbItem = input.Adapt(); thumbItem.FileName = saveFileName.Replace(extName, $"_thumb{extName}"); thumbItem.FilePath = Path.Combine(savePath, thumbFileName); thumbItem.FileSize = new FileInfo(thumbPath).Length; thumbItem.FileExtName = extName; } AddResourceFileInput item = input.Adapt(); item.FileName = saveFileName; item.FilePath = Path.Combine(savePath, fileName); item.FileSize = input.File.Length; item.FileExtName = extName; return await Add(item, thumbItem); } /// /// 添加资源文件 /// /// /// 缩略图 /// public async Task Add(AddResourceFileInput input, AddResourceFileInput thumbInput = null) { var item = input.Adapt(); await _rep.InsertAsync(item); var ret = item.Adapt(); if (thumbInput != null) { var thumbItem = thumbInput.Adapt(); await _rep.InsertAsync(thumbItem); ret.ThumbResourceFile = thumbItem.Adapt(); } return ret; } /// /// 删除资源文件 /// /// /// public async Task Del(BaseId input) { var item = await _rep.FirstOrDefaultAsync(t => t.Id == input.Id) ?? throw Oops.Oh(ErrorCode.E2001); var fpath = Path.Combine(_eqmSiteOptions.ResourceFileRoot, item.FilePath); if (File.Exists(fpath)) { File.Delete(fpath); } await item.DeleteAsync(); } /// /// 根据ID获取资源详细 /// /// /// public async Task GetById(long id) { var item = await _rep.FirstOrDefaultAsync(t => t.Id == id) ?? throw Oops.Oh(ErrorCode.E2001); return item.Adapt(); } /// /// 根据类型和源ID获取资源列表 /// /// /// /// public async Task> GetListBySourceId(ResourceFileType type, long sourceId) { var items = await _rep.DetachedEntities.Where(t => t.Type == type && t.SourceId == sourceId).ProjectToType().ToListAsync(); return items; } }