在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中实现安全高效的文件上传与下载功能,并结合最佳实践确保应用的稳定性和可维护性。