HaniBlindBox/server/HoneyBox/src/HoneyBox.Admin/Controllers/UploadController.cs
2026-01-28 22:02:26 +08:00

179 lines
5.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using HoneyBox.Core.Interfaces;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace HoneyBox.Admin.Controllers;
/// <summary>
/// 文件上传控制器
/// </summary>
[ApiController]
[Route("api/admin/upload")]
[Authorize]
public class UploadController : ControllerBase
{
private readonly IImageUploadService _uploadService;
private readonly ILogger<UploadController> _logger;
private static readonly HashSet<string> AllowedImageExtensions = new(StringComparer.OrdinalIgnoreCase)
{
".jpg", ".jpeg", ".png", ".gif", ".webp", ".avif"
};
private const long MaxFileSize = 20 * 1024 * 1024; // 20MB
public UploadController(IImageUploadService uploadService, ILogger<UploadController> logger)
{
_uploadService = uploadService;
_logger = logger;
}
/// <summary>
/// 获取预签名上传URL当前不支持直传返回标识让前端降级
/// </summary>
[HttpPost("presigned-url")]
public IActionResult GetPresignedUrl([FromBody] PresignedUrlRequest request)
{
// 当前不支持直传,返回标识让前端降级到服务端上传
return Ok(new
{
code = 0,
message = "success",
data = new { supportsDirectUpload = false }
});
}
/// <summary>
/// 上传图片(服务端上传)
/// </summary>
[HttpPost("image")]
[RequestSizeLimit(MaxFileSize)]
public async Task<IActionResult> UploadImage(IFormFile file)
{
if (file == null || file.Length == 0)
{
return Ok(new { code = 1, message = "请选择要上传的图片" });
}
if (file.Length > MaxFileSize)
{
return Ok(new { code = 1, message = "图片大小不能超过20MB" });
}
var extension = Path.GetExtension(file.FileName);
if (!AllowedImageExtensions.Contains(extension))
{
return Ok(new { code = 1, message = "不支持的图片格式,仅支持 jpg/jpeg/png/gif/webp/avif" });
}
try
{
using var stream = file.OpenReadStream();
var url = await _uploadService.UploadStreamAsync(stream, file.FileName, file.ContentType, "uploads");
if (!string.IsNullOrEmpty(url))
{
return Ok(new
{
code = 0,
message = "上传成功",
data = new
{
url,
fileName = file.FileName,
fileSize = file.Length
}
});
}
else
{
return Ok(new { code = 1, message = "上传失败" });
}
}
catch (Exception ex)
{
_logger.LogError(ex, "图片上传异常: {FileName}", file.FileName);
return Ok(new { code = 1, message = "上传失败,请稍后重试" });
}
}
/// <summary>
/// 批量上传图片
/// </summary>
[HttpPost("images")]
[RequestSizeLimit(MaxFileSize * 10)]
public async Task<IActionResult> UploadImages(List<IFormFile> files)
{
if (files == null || files.Count == 0)
{
return Ok(new { code = 1, message = "请选择要上传的图片" });
}
var results = new List<object>();
var errors = new List<string>();
foreach (var file in files)
{
if (file.Length > MaxFileSize)
{
errors.Add($"{file.FileName}: 文件大小超过限制");
continue;
}
var extension = Path.GetExtension(file.FileName);
if (!AllowedImageExtensions.Contains(extension))
{
errors.Add($"{file.FileName}: 不支持的图片格式");
continue;
}
try
{
using var stream = file.OpenReadStream();
var url = await _uploadService.UploadStreamAsync(stream, file.FileName, file.ContentType, "uploads");
if (!string.IsNullOrEmpty(url))
{
results.Add(new
{
url,
fileName = file.FileName,
fileSize = file.Length
});
}
else
{
errors.Add($"{file.FileName}: 上传失败");
}
}
catch (Exception ex)
{
_logger.LogError(ex, "图片上传异常: {FileName}", file.FileName);
errors.Add($"{file.FileName}: 上传异常");
}
}
if (results.Count == 0)
{
return Ok(new { code = 1, message = string.Join("; ", errors) });
}
return Ok(new
{
code = 0,
message = errors.Count > 0 ? $"部分上传成功,失败: {string.Join("; ", errors)}" : "上传成功",
data = results
});
}
}
/// <summary>
/// 预签名URL请求
/// </summary>
public class PresignedUrlRequest
{
public string FileName { get; set; } = string.Empty;
public string ContentType { get; set; } = string.Empty;
public long FileSize { get; set; }
}