在ASP.NET MVC中处理大文件上传是一个常见的需求,但默认的文件上传机制有一些限制。传统表单上传使用HttpPostedFileBase
或IFormFile
,但这种方式对于大文件(如超过100MB)会遇到以下问题:
原理:将大文件分割成小块,逐块上传并在服务器端重新组合。
优势:
实现代码:
前端(JavaScript):
async function uploadFile(file) {
const chunkSize = 5 * 1024 * 1024; // 5MB每块
const totalChunks = Math.ceil(file.size / chunkSize);
for (let chunkNumber = 0; chunkNumber < totalChunks; chunkNumber++) {
const start = chunkNumber * chunkSize;
const end = Math.min(start + chunkSize, file.size);
const chunk = file.slice(start, end);
const formData = new FormData();
formData.append('file', chunk);
formData.append('chunkNumber', chunkNumber);
formData.append('totalChunks', totalChunks);
formData.append('fileName', file.name);
await fetch('/Upload/ChunkUpload', {
method: 'POST',
body: formData
});
}
}
后端(C#):
[HttpPost]
public async Task<ActionResult> ChunkUpload()
{
var chunkNumber = int.Parse(Request.Form["chunkNumber"]);
var totalChunks = int.Parse(Request.Form["totalChunks"]);
var fileName = Request.Form["fileName"];
var chunk = Request.Files[0];
var tempPath = Path.Combine(Path.GetTempPath(), "Uploads");
Directory.CreateDirectory(tempPath);
var chunkPath = Path.Combine(tempPath, $"{fileName}.part{chunkNumber}");
using (var stream = new FileStream(chunkPath, FileMode.Create))
{
await chunk.CopyToAsync(stream);
}
if (chunkNumber == totalChunks - 1)
{
// 所有块上传完成,合并文件
var finalPath = Path.Combine(Server.MapPath("~/Uploads"), fileName);
using (var finalStream = new FileStream(finalPath, FileMode.Create))
{
for (int i = 0; i < totalChunks; i++)
{
var partPath = Path.Combine(tempPath, $"{fileName}.part{i}");
using (var partStream = new FileStream(partPath, FileMode.Open))
{
await partStream.CopyToAsync(finalStream);
}
File.Delete(partPath);
}
}
}
return Json(new { success = true });
}
原理:直接读取请求流,避免将整个文件加载到内存。
优势:
实现代码:
[HttpPost]
public async Task<ActionResult> StreamUpload()
{
var fileName = Request.Headers["X-File-Name"];
var uploadPath = Path.Combine(Server.MapPath("~/Uploads"), fileName);
using (var fileStream = new FileStream(uploadPath, FileMode.Create))
{
await Request.InputStream.CopyToAsync(fileStream);
}
return Json(new { success = true });
}
优势:
实现代码:
前端:
function uploadWithProgress(file) {
const xhr = new XMLHttpRequest();
const formData = new FormData();
formData.append('file', file);
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
const percent = Math.round((e.loaded / e.total) * 100);
console.log(`${percent}% uploaded`);
}
};
xhr.onload = function() {
if (xhr.status === 200) {
console.log('Upload complete');
}
};
xhr.open('POST', '/api/upload', true);
xhr.send(formData);
}
在Web.config中增加以下配置以支持大文件上传:
<system.web>
<httpRuntime maxRequestLength="2097152" executionTimeout="3600" />
</system.web>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483648" />
</requestFiltering>
</security>
</system.webServer>
executionTimeout
值IFormFile
或HttpPostedFileBase
通过以上方法,可以有效地在ASP.NET MVC中实现大文件上传功能,解决传统上传方式的限制问题。
没有搜到相关的文章