You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core MVC Ajax上传文件返回400 Bad Request问题

解决Ajax上传分部视图表单文件时的400 Bad Request问题

你的问题主要出在模型绑定方式、FormData的传递逻辑以及防伪造Token的处理上,下面一步步帮你修正:

1. 修正Action的模型绑定特性

你当前用了[FromBody],但上传文件用的是multipart/form-data格式的表单数据,而非JSON,这个特性会导致ASP.NET Core无法正确解析FormData中的文件,直接返回400错误。

修改后的Action代码:

[HttpPost]
[ValidateAntiForgeryToken] // 显式启用防伪造验证,确保安全
public async Task<IActionResult> UploadFile([FromForm] ApplicationsFileCreateInputModel createInputModel)
{
    var fileId = await applicationFileService.UploadAsync(createInputModel);
    return Json(fileId);
}

2. 给分部视图表单添加防伪造Token

你的表单没有生成防伪造Token的隐藏域,需要手动添加(ASP.NET Core的asp-form标签助手会自动生成,但你用的是普通<form>):

修改后的分部视图代码:

@using ArkStore.App.Models.BindingModels.ApplicationFiles
@model ApplicationsFileCreateInputModel
<form enctype="multipart/form-data" method="post">
    @Html.AntiForgeryToken() <!-- 新增这一行,生成防伪造Token隐藏域 -->
    <div class="custom-file w-50 mb-2">
        <label class="custom-file-label" asp-for="AppApk"></label>
        <input class="custom-file-input" asp-for="AppApk" id="appApk" type="file">
        <span asp-validation-for="AppApk" class="text-danger"></span>
    </div>
    <div class="custom-file w-50 mb-2">
        <label class="custom-file-label" asp-for="Thumbnail"></label>
        <input class="custom-file-input" asp-for="Thumbnail" id="thumbnail" type="file">
        <span asp-validation-for="Thumbnail" class="text-danger"></span>
    </div>
    <div class="form-group">
        <button id="upload" type="submit" class="btn btn-primary">Upload</button>
    </div>
</form>

3. 修正Ajax的FormData传递逻辑

之前你把FormData嵌套在data字段里,还单独传递Token,这会导致服务器无法正确解析表单数据。正确的做法是直接把包含Token的FormData作为请求数据发送:

修改后的Ajax代码:

function setUploadFileId() {
    const targetForm = document.forms[1];
    const formData = new FormData(targetForm); // 直接从表单创建FormData,自动包含Token和文件
    
    $.ajax({
        url: "https://localhost:44377/Applications/UploadFile",
        type: "POST",
        data: formData,
        contentType: false, // 让浏览器自动设置正确的multipart/form-data头
        processData: false, // 不要处理FormData,避免jQuery自动序列化
        success: function (id) {
            $("#fileId").val(id);
        },
        error: function (error) {
            console.log(error);
        }
    });
}

$("#upload").on("click", function (evt) {
    evt.preventDefault();
    setUploadFileId();
});

关键问题解释

  • [FromBody] vs [FromForm]:[FromBody]用于解析请求体中的JSON数据,而文件上传用的是表单格式,必须用[FromForm]才能正确绑定IFormFile类型的参数。
  • 防伪造Token的传递:Token必须包含在FormData中一起发送,通过@Html.AntiForgeryToken()生成的隐藏域会被自动加入FormData,服务器才能验证通过。
  • contentType和processData设置:这两个参数设为false是为了让浏览器自动处理multipart/form-data的请求头和边界,避免jQuery对FormData做错误的序列化。

你可以在浏览器开发者工具的网络标签里查看请求,确认FormData中包含了两个文件和__RequestVerificationToken,这样就能正常上传了。

内容的提问来源于stack exchange,提问作者User001

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:46:26