using Apimanager_backend.Exceptions; using Apimanager_backend.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using SixLabors.ImageSharp; // 确保添加这个using using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats.Png; using Apimanager_backend.Dtos; namespace Apimanager_backend.Controllers { [ApiController] [Route("api/[controller]/[action]")] public class UploadController:ControllerBase { private ILogger _logger; private readonly IWebHostEnvironment _environment; private IUserService _userService; // 最大文件大小 5MB private const long MaxFileSize = 5 * 1024 * 1024; // 允许的文件类型 private static readonly string[] AllowedExtensions = { ".jpg", ".jpeg", ".png", ".gif" }; public UploadController(ILogger logger,IWebHostEnvironment webHostEnvironment,IUserService userService) { _logger = logger; _environment = webHostEnvironment; _userService = userService; } [HttpPost] [Authorize(Roles = "User")] public async Task UploadPic(IFormFile file) { try { // 1. 验证文件 if (file == null || file.Length == 0) { throw new BaseException(1001,"缺少文件"); } // 2. 验证文件大小 if (file.Length > MaxFileSize) { throw new BaseException(1001, $"文件大小不能超过{MaxFileSize}"); } var basePath = _environment.WebRootPath ?? _environment.ContentRootPath; // 3. 验证文件类型 var extension = Path.GetExtension(file.FileName).ToLowerInvariant(); if (string.IsNullOrEmpty(extension) || !AllowedExtensions.Contains(extension)) { throw new BaseException(1001, "只支持 JPG, PNG, GIF 格式的图片"); } // 5. 创建存储目录 var uploadsFolder = Path.Combine(basePath, "uploads", "avatars"); if (!Directory.Exists(uploadsFolder)) { Directory.CreateDirectory(uploadsFolder); } var userId = User.Claims.First(x => x.Type == "userId").Value; // 6. 生成唯一文件名 var uniqueFileName = $"{userId}_{DateTime.Now:yyyyMMddHHmmss}{extension}"; var filePath = Path.Combine(uploadsFolder, uniqueFileName); // 7. 处理并保存图片 using (var image = await Image.LoadAsync(file.OpenReadStream())) { // 调整图片大小(最大200x200) image.Mutate(x => x.Resize(new ResizeOptions { Size = new Size(200, 200), Mode = ResizeMode.Max })); // 保存为高质量JPEG await image.SaveAsync(filePath); } // 8. 更新数据库中的头像路径 var avatarUrl = $"/uploads/avatars/{uniqueFileName}"; var result = await _userService.UpdateUserAvatarAsync(int.Parse(userId), avatarUrl); if (!result) { // 如果数据库更新失败,删除已上传的文件 System.IO.File.Delete(filePath); throw new BaseException(1004,"头像上传失败"); } // 9. 返回成功响应 return Ok(new ResponseBase(1000,"头像上传成功",null)); } catch (Exception ex) { _logger.LogError(ex, "头像上传失败"); throw new BaseException(1004, "头像上传失败"); } } [HttpPost] [Authorize(Roles = "Admin")] public async Task UploadLogo(IFormFile file) { try { // 1. 验证文件 if (file == null || file.Length == 0) { throw new BaseException(1001, "缺少文件"); } // 2. 验证文件大小 if (file.Length > MaxFileSize) { throw new BaseException(1001, $"文件大小不能超过{MaxFileSize}"); } var basePath = _environment.WebRootPath ?? _environment.ContentRootPath; // 3. 验证文件类型 var extension = Path.GetExtension(file.FileName).ToLowerInvariant(); if (string.IsNullOrEmpty(extension) || !AllowedExtensions.Contains(extension)) { throw new BaseException(1001, "只支持 JPG, PNG, GIF 格式的图片"); } // 5. 创建存储目录 var uploadsFolder = Path.Combine(basePath,"uploads"); var filePath = Path.Combine(uploadsFolder, "logo.png"); // 7. 处理并保存图片 using (var image = await Image.LoadAsync(file.OpenReadStream())) { // 调整图片大小(最大200x200) /* image.Mutate(x => x.Resize(new ResizeOptions { Size = new Size(200, 200), Mode = ResizeMode.Max })); */ // 强制保存为PNG(高质量) await image.SaveAsync(filePath, new PngEncoder { CompressionLevel = PngCompressionLevel.BestCompression // 最佳压缩 }); } // 9. 返回成功响应 return Ok(new ResponseBase(1000, "LOGO上传成功", null)); } catch (Exception ex) { _logger.LogError(ex, "LOGO上传失败"); throw new BaseException(1004, "LOGO上传失败"); } } [HttpPost] [Authorize(Roles = "Admin")] public async Task UploadFavicon(IFormFile file) { try { // 1. 验证文件 if (file == null || file.Length == 0) { throw new BaseException(1001, "缺少文件"); } // 2. 验证文件大小 if (file.Length > MaxFileSize) { throw new BaseException(1001, $"文件大小不能超过{MaxFileSize}"); } var basePath = _environment.WebRootPath ?? _environment.ContentRootPath; // 3. 验证文件类型 var extension = Path.GetExtension(file.FileName).ToLowerInvariant(); if (string.IsNullOrEmpty(extension) || extension != ".ico") { throw new BaseException(1001, "只支持 ICO 格式的图片"); } // 3. 保存到网站根目录 var icoPath = Path.Combine(basePath,"uploads", "favicon.ico"); using (var stream = new FileStream(icoPath, FileMode.Create)) { await file.CopyToAsync(stream); } // 9. 返回成功响应 return Ok(new ResponseBase(1000, "favicon上传成功", null)); } catch (Exception ex) { _logger.LogError(ex, "Favicon上传失败"); throw new BaseException(1004, "Favicon上传失败"); } } [HttpPost] [Authorize(Roles = "Admin")] public async Task UploadApi(IFormFile file) { if (file == null || file.Length == 0) throw new BaseException(1001,"请上传文件"); // 检查扩展名 var ext = Path.GetExtension(file.FileName); if (ext != ".dll") throw new BaseException(1001, "只允许上传DLL"); // 插件保存路径 var saveDir = Path.Combine(_environment.ContentRootPath, "ApiHandler"); if (!Directory.Exists(saveDir)) Directory.CreateDirectory(saveDir); var filePath = Path.Combine(saveDir, file.FileName); // 保存文件 using (var stream = new FileStream(filePath, FileMode.Create)) { await file.CopyToAsync(stream); } return Ok(new ResponseBase(1000,"上传成功",null)); } } }