上传文件过大时如何显示有意义的错误提示?
解决ASP.NET Core文件上传大小限制后的友好错误提示及防DoS问题
问题原因
使用RequestFormLimitsAttribute设置的上传大小限制是在ASP.NET Core请求管道的早期阶段生效的,当上传文件超出限制时,服务器会直接返回413 Request Entity Too Large错误,此时请求还未到达你的PageModel的OnPostAsync方法,因此无法在页面逻辑里捕获处理,导致浏览器(如Edge)显示通用错误页面。
解决方案
1. 全局捕获413错误并返回友好提示
通过自定义中间件在管道中捕获413错误,重定向回上传页面并携带错误信息,让用户看到自定义提示。
自定义中间件示例
在Program.cs中添加以下中间件(放在app.UseRouting()之后、app.UseAuthorization()之前):
app.Use(async (context, next) => { await next(); // 检查是否触发413错误 if (context.Response.StatusCode == StatusCodes.Status413RequestEntityTooLarge) { // 重定向回上传页面并携带错误标识 var returnUrl = "/BulkTruckUpload?error=fileOverLimit"; context.Response.Redirect(returnUrl); } });
在BulkTruckUploadModel中处理错误参数:
public class BulkTruckUploadModel : PageModel { [TempData] public string ErrorMsg { get; set; } public void OnGet(string error) { if (error == "fileOverLimit") { ErrorMsg = $"上传文件大小超出限制,最大允许{MaxUploadFileLength / (1024 * 1024)}MB"; } } // 你的OnPostAsync方法... }
在视图中展示错误信息:
@if (!string.IsNullOrEmpty(Model.ErrorMsg)) { <div class="alert alert-danger">@Model.ErrorMsg</div> }
2. 客户端预检查(JavaScript)
在用户提交表单前用JS检查文件大小,提前阻止大文件提交,既提升用户体验,也减少服务器不必要的请求:
<form method="post" enctype="multipart/form-data" onsubmit="return checkFileSize()"> <!-- 表单原有内容 --> <script> function checkFileSize() { const fileInput = document.querySelector('input[type="file"]'); const maxAllowedSize = @Model.MaxUploadFileLength; // 从后端获取限制值 if (fileInput.files.length > 0) { const selectedFile = fileInput.files[0]; if (selectedFile.size > maxAllowedSize) { alert(`文件大小超出限制,最大允许${(maxAllowedSize / (1024 * 1024)).toFixed(2)}MB`); return false; // 阻止表单提交 } } return true; } </script> </form>
3. 服务器端二次验证(防止绕过客户端限制)
即使做了客户端检查,也要在服务器端再次验证文件大小,防止攻击者绕过客户端限制:
public async Task<IActionResult> OnPostAsync() { if (ModelState.IsValid) { try { var uploadFile = BulkUpload.File; if (uploadFile.Length > MaxUploadFileLength) { ModelState.AddModelError("BulkUpload.File", $"文件大小超出限制,最大允许{MaxUploadFileLength / (1024 * 1024)}MB"); return Page(); } // 正常处理文件逻辑 } catch (Exception ex) { ModelState.AddModelError(string.Empty, "上传过程中发生错误,请重试"); } } return Page(); }
关于防DoS的疑问
绝对不要移除RequestFormLimitsAttribute,如果移除后再检查文件大小,服务器会先接收完整的大文件,这会消耗大量带宽和服务器资源,完全起不到防DoS的作用。
RequestFormLimitsAttribute的核心作用是在请求管道早期拦截超大文件,服务器不会接收整个文件内容就直接拒绝请求,这才是有效的防DoS手段。结合上面的全局错误捕获方案,既能阻止大文件上传,又能给用户显示友好提示,兼顾安全性和用户体验。
内容的提问来源于stack exchange,提问作者Jonathan Wood
相关产品推荐
相关产品推荐

