Files
DRS9.Dashboard/src/DRS9.Dashboard.Server/Controllers/FileUploadController.cs

245 lines
7.3 KiB
C#
Raw Normal View History

2026-01-13 17:57:48 +08:00
using Microsoft.AspNetCore.Mvc;
namespace DRS9.Dashboard.Server.Controllers;
[ApiController]
[Route("api/admin/[controller]")]
// [Authorize] - 暂时禁用认证以便测试
public class UploadController : ControllerBase
{
private readonly IWebHostEnvironment _environment;
private readonly ILogger<UploadController> _logger;
// 允许的图片扩展名
private static readonly string[] ImageExtensions = { ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".svg", ".webp" };
// 允许的视频扩展名
private static readonly string[] VideoExtensions = { ".mp4", ".webm", ".ogg", ".mov", ".avi", ".mkv" };
// 最大文件大小 (50MB)
private const long MaxFileSize = 50 * 1024 * 1024;
public UploadController(IWebHostEnvironment environment, ILogger<UploadController> logger)
{
_environment = environment;
_logger = logger;
}
/// <summary>
/// 上传文件(图片或视频)
/// </summary>
[HttpPost]
public async Task<ActionResult<object>> UploadFile(IFormFile file)
{
if (file == null || file.Length == 0)
{
return BadRequest(new { success = false, message = "请选择文件" });
}
// 检查文件大小
if (file.Length > MaxFileSize)
{
return BadRequest(new { success = false, message = $"文件大小不能超过 {MaxFileSize / 1024 / 1024}MB" });
}
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
// 确定文件类型
string itemType;
string subFolder;
if (ImageExtensions.Contains(extension))
{
itemType = "Image";
subFolder = "images";
}
else if (VideoExtensions.Contains(extension))
{
itemType = "Video";
subFolder = "videos";
}
else
{
return BadRequest(new { success = false, message = "不支持的文件类型,请上传图片或视频" });
}
try
{
// 创建上传目录
var uploadsFolder = Path.Combine(_environment.WebRootPath, "uploads", subFolder);
if (!Directory.Exists(uploadsFolder))
{
Directory.CreateDirectory(uploadsFolder);
}
// 生成唯一文件名
var uniqueFileName = $"{Guid.NewGuid()}{extension}";
var filePath = Path.Combine(uploadsFolder, uniqueFileName);
// 保存文件
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
// 返回文件 URL
var fileUrl = $"/uploads/{subFolder}/{uniqueFileName}";
_logger.LogInformation("文件上传成功: {FileName} -> {Url}", file.FileName, fileUrl);
return Ok(new
{
success = true,
message = "上传成功",
url = fileUrl,
itemType = itemType,
fileName = file.FileName
});
}
catch (Exception ex)
{
_logger.LogError(ex, "文件上传失败");
return StatusCode(500, new { success = false, message = $"上传失败: {ex.Message}" });
}
}
/// <summary>
/// 批量上传文件
/// </summary>
[HttpPost("batch")]
public async Task<ActionResult<object>> UploadFiles(List<IFormFile> files)
{
if (files == null || files.Count == 0)
{
return BadRequest(new { success = false, message = "请选择文件" });
}
var results = new List<object>();
var successCount = 0;
var failCount = 0;
foreach (var file in files)
{
var result = await UploadSingleFile(file);
if (result.success)
{
successCount++;
}
else
{
failCount++;
}
results.Add(new
{
fileName = file.FileName,
success = result.success,
message = result.message,
url = result.url,
itemType = result.itemType
});
}
return Ok(new
{
success = true,
message = $"上传完成: {successCount} 个成功, {failCount} 个失败",
results = results
});
}
private async Task<(bool success, string message, string? url, string? itemType)> UploadSingleFile(IFormFile file)
{
if (file == null || file.Length == 0)
{
return (false, "请选择文件", null, null);
}
if (file.Length > MaxFileSize)
{
return (false, $"文件大小不能超过 {MaxFileSize / 1024 / 1024}MB", null, null);
}
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
string itemType;
string subFolder;
if (ImageExtensions.Contains(extension))
{
itemType = "Image";
subFolder = "images";
}
else if (VideoExtensions.Contains(extension))
{
itemType = "Video";
subFolder = "videos";
}
else
{
return (false, "不支持的文件类型", null, null);
}
try
{
var uploadsFolder = Path.Combine(_environment.WebRootPath, "uploads", subFolder);
if (!Directory.Exists(uploadsFolder))
{
Directory.CreateDirectory(uploadsFolder);
}
var uniqueFileName = $"{Guid.NewGuid()}{extension}";
var filePath = Path.Combine(uploadsFolder, uniqueFileName);
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
var fileUrl = $"/uploads/{subFolder}/{uniqueFileName}";
return (true, "上传成功", fileUrl, itemType);
}
catch (Exception ex)
{
_logger.LogError(ex, "文件上传失败: {FileName}", file.FileName);
return (false, $"上传失败: {ex.Message}", null, null);
}
}
/// <summary>
/// 删除文件
/// </summary>
[HttpDelete]
public ActionResult DeleteFile([FromBody] FileDeleteRequest request)
{
if (string.IsNullOrWhiteSpace(request.Url))
{
return BadRequest(new { success = false, message = "请提供文件 URL" });
}
try
{
// 从 URL 中提取文件路径
var filePath = Path.Combine(_environment.WebRootPath, request.Url.TrimStart('/'));
if (System.IO.File.Exists(filePath))
{
System.IO.File.Delete(filePath);
_logger.LogInformation("文件删除成功: {Url}", request.Url);
return Ok(new { success = true, message = "删除成功" });
}
else
{
return NotFound(new { success = false, message = "文件不存在" });
}
}
catch (Exception ex)
{
_logger.LogError(ex, "文件删除失败: {Url}", request.Url);
return StatusCode(500, new { success = false, message = $"删除失败: {ex.Message}" });
}
}
}
public class FileDeleteRequest
{
public string Url { get; set; } = string.Empty;
}