ASP.NET Core中的文件上传与下载处理

在ASP.NET Core中,文件上传与下载处理是常见的功能需求,以下是详细的实现步骤与最佳实践。

1. 文件上传处理

基本实现

通过IFormFile接口处理文件上传。

示例代码:上传文件到服务器

Controller代码

[ApiController]
[Route("api/[controller]")]
public class FileController : ControllerBase
{
    private readonly string _uploadPath = Path.Combine(Directory.GetCurrentDirectory(), "Uploads");

    [HttpPost("upload")]
    public async Task<IActionResult> Upload(IFormFile file)
    {
        if (file == null || file.Length == 0)
            return BadRequest("Please upload a valid file.");

        var filePath = Path.Combine(_uploadPath, file.FileName);

        Directory.CreateDirectory(_uploadPath); // 确保目录存在

        using (var stream = new FileStream(filePath, FileMode.Create))
        {
            await file.CopyToAsync(stream);
        }

        return Ok(new { FilePath = filePath });
    }
}

多文件上传

支持通过List<IFormFile>处理多个文件的上传。

示例代码:支持多文件上传

[HttpPost("upload-multiple")]
public async Task<IActionResult> UploadMultiple(List<IFormFile> files)
{
    if (files == null || files.Count == 0)
        return BadRequest("No files uploaded.");

    var uploadedFiles = new List<string>();

    foreach (var file in files)
    {
        var filePath = Path.Combine(_uploadPath, file.FileName);
        using (var stream = new FileStream(filePath, FileMode.Create))
        {
            await file.CopyToAsync(stream);
        }
        uploadedFiles.Add(filePath);
    }

    return Ok(new { UploadedFiles = uploadedFiles });
}

安全与验证

限制文件类型

验证文件的ContentType或扩展名。

var allowedExtensions = new[] { ".jpg", ".png", ".pdf" };
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
if (!allowedExtensions.Contains(extension))
    return BadRequest("Invalid file type.");

限制文件大小

使用RequestSizeLimit或通过配置限制上传大小。

[RequestSizeLimit(10 * 1024 * 1024)] // 10MB
[HttpPost("upload")]
public IActionResult UploadLimited(IFormFile file)
{
    // Implementation here
}

2. 文件下载处理

基本实现

通过FileResult提供文件下载。

示例代码:文件下载

[HttpGet("download/{fileName}")]
public IActionResult Download(string fileName)
{
    var filePath = Path.Combine(_uploadPath, fileName);

    if (!System.IO.File.Exists(filePath))
        return NotFound("File not found.");

    var contentType = "application/octet-stream";
    var fileBytes = System.IO.File.ReadAllBytes(filePath);

    return File(fileBytes, contentType, fileName);
}

支持大文件下载

使用流式传输处理大文件,避免内存占用过高。

示例代码:流式下载大文件

[HttpGet("download-stream/{fileName}")]
public IActionResult DownloadStream(string fileName)
{
    var filePath = Path.Combine(_uploadPath, fileName);

    if (!System.IO.File.Exists(filePath))
        return NotFound("File not found.");

    var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
    var contentType = "application/octet-stream";

    return File(stream, contentType, fileName);
}

3. 前端与后端的协作

前端示例:文件上传

使用HTML和JavaScript实现简单的上传表单。

<form id="uploadForm" enctype="multipart/form-data">
    <input type="file" name="file" id="fileInput" />
    <button type="submit">Upload</button>
</form>
<script>
    const form = document.getElementById('uploadForm');
    form.addEventListener('submit', async (e) => {
        e.preventDefault();
        const formData = new FormData();
        formData.append('file', document.getElementById('fileInput').files[0]);

        const response = await fetch('/api/file/upload', {
            method: 'POST',
            body: formData,
        });
        const result = await response.json();
        console.log(result);
    });
</script>

前端示例:文件下载

通过JavaScript触发文件下载。

<button id="downloadButton">Download File</button>
<script>
    document.getElementById('downloadButton').addEventListener('click', async () => {
        const response = await fetch('/api/file/download/sample.pdf');
        const blob = await response.blob();
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'sample.pdf';
        a.click();
        window.URL.revokeObjectURL(url);
    });
</script>

4. 最佳实践

存储路径

避免将文件存储在wwwroot目录,使用独立目录存储用户上传的文件。

数据保护

文件路径与名称需进行加密或哈希处理。

避免用户通过猜测URL直接访问文件。

文件清理

定期清理无用文件,避免磁盘占用过高。

日志与监控

对上传与下载操作进行日志记录,便于排查问题。

通过上述方法,您可以在ASP.NET Core中实现安全高效的文件上传与下载功能,并结合最佳实践确保应用的稳定性和可维护性。

评论