using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; namespace AdminService.ImageUpload { public class ImageUploadService : IImageUploadService { private readonly ILogger _logger; private static readonly string[] AllowedExtensions = { ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp" }; private const long MaxFileSize = 5 * 1024 * 1024; // 5MB private const string UploadFolder = "wwwroot/uploads/temp"; public ImageUploadService(ILogger logger) { _logger = logger; } public bool ValidateImage(IFormFile file, out string errorMessage) { errorMessage = string.Empty; if (file == null || file.Length == 0) { errorMessage = "请选择要上传的文件"; return false; } var ext = Path.GetExtension(file.FileName).ToLowerInvariant(); if (!AllowedExtensions.Contains(ext)) { errorMessage = "只支持上传图片格式:jpg、jpeg、png、gif、bmp、webp"; return false; } if (file.Length > MaxFileSize) { errorMessage = "文件大小不能超过5MB"; return false; } return true; } public async Task<(bool isOk, string path, string fileName, string errorMessage)> UploadImageAsync(IFormFile file, string? customName = null) { if (!ValidateImage(file, out var errorMessage)) { return (false, string.Empty, string.Empty, errorMessage); } try { var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); string fileName; string relativePath; if (!string.IsNullOrWhiteSpace(customName)) { fileName = customName + ".png"; var uploadPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "uploads"); if (!Directory.Exists(uploadPath)) Directory.CreateDirectory(uploadPath); var filePath = Path.Combine(uploadPath, fileName); using (var stream = new FileStream(filePath, FileMode.Create)) { await file.CopyToAsync(stream); } relativePath = $"/uploads/{fileName}?timespan={timestamp}"; } else { var ext = Path.GetExtension(file.FileName).ToLowerInvariant(); fileName = Guid.NewGuid().ToString("N") + ext; var uploadPath = Path.Combine(Directory.GetCurrentDirectory(), UploadFolder); if (!Directory.Exists(uploadPath)) Directory.CreateDirectory(uploadPath); var filePath = Path.Combine(uploadPath, fileName); using (var stream = new FileStream(filePath, FileMode.Create)) { await file.CopyToAsync(stream); } relativePath = $"/uploads/temp/{fileName}?timespan={timestamp}"; } return (true, relativePath, fileName, string.Empty); } catch (Exception ex) { _logger.LogError(ex, "图片上传失败: {Message}", ex.Message); return (false, string.Empty, string.Empty, $"上传失败:{ex.Message}"); } } public async Task> UploadBatchImagesAsync(IFormFile[] files) { var results = new List(); foreach (var file in files) { var result = new BatchUploadResult { OriginalFileName = file.FileName }; if (file.Length == 0) { result.Success = false; result.Message = "文件为空"; results.Add(result); continue; } if (!ValidateImage(file, out var errorMessage)) { result.Success = false; result.Message = errorMessage; results.Add(result); continue; } try { var uploadResult = await UploadImageAsync(file); result.Success = uploadResult.isOk; result.Path = uploadResult.path; result.FileName = uploadResult.fileName; result.Message = uploadResult.errorMessage; } catch (Exception ex) { result.Success = false; result.Message = "上传失败"; _logger.LogError(ex, "批量上传中单个文件上传失败: {FileName}", file.FileName); } results.Add(result); } return results; } } }