使用jQuery与Promises上传大文件时参数为空问题求助
问题分析与解决方案
核心原因
你遇到的问题本质是大文件转Base64后导致请求体积超限,后端无法解析表单数据:
- Base64编码会让文件体积膨胀约33%,8MB的PDF转码后会变成约10.6MB,加上其他字段内容,很容易超过ASP.NET Core默认的请求大小限制(默认值通常是4MB)。
- 当请求体积超过限制时,ASP.NET Core会无法正确解析整个表单,导致所有参数都被识别为null。
- 移除
document参数后,请求体积回到限制内,所以其他参数能正常传递。
解决方案
1. 调整ASP.NET Core的请求大小限制
首先修改后端配置,允许更大的请求体积:
- 在
Program.cs中添加全局请求限制配置:
builder.Services.Configure<Microsoft.AspNetCore.Http.Features.FormOptions>(options => { // 设置最大请求体大小,这里设为20MB,可根据需求调整 options.MultipartBodyLengthLimit = 20 * 1024 * 1024; options.ValueLengthLimit = 20 * 1024 * 1024; });
- 或者在对应的Action上添加特性,单独设置限制:
[HttpPost] [RequestSizeLimit(20 * 1024 * 1024)] // 20MB限制 public IActionResult SubmitMaintainBook(...) { // 你的业务逻辑 }
2. 前端改用FormData直接上传文件(替代Base64)
Base64上传大文件不仅体积膨胀,还容易触发请求限制,推荐用标准的FormData方式上传,更高效且稳定。修改前端代码如下:
function SubmitMaintainBook() { if (!ValidateMaintainBook()) return; // 创建FormData对象,用于包装所有字段和文件 const formData = new FormData(); // 添加文本字段 formData.append("id", $("#hdnId").val()); formData.append("courseName", $("#txtCourseName").val()); formData.append("subtitle", $("#txtSubtitle").val()); formData.append("field", $(".cmbField").find(".list").find(".selected").data("value")); formData.append("isbnAsin", $("#txtIsbnAsin").val()); formData.append("genre", $(".cmbGenre").find(".list").find(".selected").data("value")); formData.append("edition", $("#txtEdition").val()); formData.append("citation", $("#txtCitation").val()); formData.append("authors", JSON.stringify(getAuthors())); // 如果authors是数组,转成JSON字符串 formData.append("codeFront", $("#txtCodeFront").val()); formData.append("codeBack", $("#txtCodeBack").val()); formData.append("language", $(".cmbLanguage").find(".list").find(".selected").data("value")); formData.append("totalPages", $("#txtTotalPages").val()); formData.append("publisher", $("#txtPublisher").val()); formData.append("citationFormat", $(".cmbCitationFormat").find(".list").find(".selected").data("value")); formData.append("publicationDate", $("#txtPublicationFormat").val()); formData.append("description", $("#txtDescription").val()); formData.append("purchaseLink", $("#txtPurchaseLink").val()); formData.append("password", $("#hdnPassword").val()); // 添加图片文件及相关信息 const imageFile = $('#image-input')[0].files[0]; if (imageFile) { formData.append("image", imageFile); formData.append("imageName", imageFile.name); formData.append("imageType", imageFile.type); } // 添加PDF文件及相关信息 const docFile = $('#pdf__file--download')[0].files[0]; if (docFile) { formData.append("document", docFile); formData.append("documentName", docFile.name); formData.append("documentType", docFile.type); } $.ajax({ timeout: 20000, url: "/Library/SubmitMaintainBook", async: true, // 去掉同步请求,异步更符合现代前端规范 cache: false, type: "POST", data: formData, processData: false, // 关键:不要让jQuery处理FormData contentType: false, // 关键:让浏览器自动设置正确的Content-Type(multipart/form-data) success: function(jsonData) { if (!jsonData.result) { alert(jsonData.errorMessage); } else { bootstrap.Modal(document.getElementById('MaintainBook')).hide(); const maintainBookModalSuccess = new bootstrap.Modal(document.getElementById('MaintainBookSuccess')); maintainBookModalSuccess.show(); } }, error: function(xhr, ajaxOptions, thrownError) { console.error("上传失败:", thrownError, xhr.responseText); // 添加错误日志,方便调试 } }); }
3. 后端调整参数接收方式
修改Action,用IFormFile接收上传的文件,同时接收其他文本字段:
首先定义视图模型(如果还没有):
public class BookViewModel { public int Id { get; set; } public string CourseName { get; set; } public string Subtitle { get; set; } // 其他文本字段,对应前端的formData键名 public string Authors { get; set; } // 如果是数组,后端可以反序列化 // ... 省略其他字段 }
然后修改Action:
[HttpPost] [RequestSizeLimit(20 * 1024 * 1024)] public IActionResult SubmitMaintainBook(BookViewModel model, IFormFile image, IFormFile document) { // 处理authors数组(如果前端传的是JSON字符串) var authors = JsonSerializer.Deserialize<List<string>>(model.Authors); // 处理图片文件:比如保存到服务器或数据库 if (image != null) { using var stream = new FileStream($"wwwroot/images/{image.FileName}", FileMode.Create); image.CopyTo(stream); } // 处理PDF文件 if (document != null) { using var stream = new FileStream($"wwwroot/docs/{document.FileName}", FileMode.Create); document.CopyTo(stream); } // 其他业务逻辑 return Json(new { result = true }); }
调试建议
- 打开浏览器开发者工具(F12),切换到Network标签,查看POST请求的状态码:如果是413,说明确实是请求体积超限。
- 查看后端日志,确认是否有请求大小超限的报错信息。
- 测试时可以逐步增大文件大小,验证配置的限制是否生效。
内容的提问来源于stack exchange,提问作者Vladimir Lenin
相关产品推荐
相关产品推荐

