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

Ajax以JSON提交带文件表单时document字段为null问题咨询

问题根因

document字段接收为null是必然结果:JSON.stringify() 没有序列化File/Blob类型二进制对象的能力,你把File实例塞进普通JS对象再做JSON序列化时,文件字段会被直接序列化为空对象{},最终发往后端的JSON请求体里根本没有有效文件数据,后端按JSON格式反序列化自然拿不到对应值。
补充:application/json是纯文本编码格式,本身不支持承载二进制文件内容,这是协议层面的限制。你之前直接提交FormData、设置contentType: false、processData: false能拿到值,是因为multipart/form-data编码天生支持混合传输文本字段和二进制文件,走的是表单模型绑定逻辑,和JSON反序列化是完全独立的两套机制。

推荐方案(无兼容问题、性能最优)

放弃application/json提交方式,将所有字段(包括普通文本和文件)统一追加到FormData中,后端去掉入参上的[FromBody]特性,ASP.NET Core会自动按multipart/form-data格式完成嵌套对象的模型绑定,不需要修改现有实体类定义。

前端Ajax代码修改

const formData = new FormData();
// 追加普通文本字段
formData.append('Title', "Lorem ipsum");
formData.append('Text', "Lorem ipsum");
// 嵌套对象字段按 [外层属性名.内层属性名] 格式追加,即可自动映射到嵌套类
formData.append('Document.file', $('#file').get(0).files[0]);
formData.append('Document.fileName', $("#fileName").val());

$.ajax({
    url: `/admin/myprofile`,
    type: "POST",
    data: formData,
    // 禁止手动设置Content-Type,让浏览器自动生成带正确boundary分隔符的multipart/form-data头
    contentType: false,
    // 禁止jQuery自动处理FormData数据
    processData: false,
    dataType: 'json',
    success: function (res) {
        // 原有成功回调逻辑
    }
});

控制器代码修改

仅需去掉入参上的[FromBody]特性,其余逻辑保持不变:

[HttpPost("myprofile")]
public IActionResult MyProfile(MyProfileDTO request)
{
    // 此处request.Document.file、request.Document.fileName均可正常取值
    return Ok();
}

注意:ASP.NET Core的表单模型绑定对属性名大小写不敏感,C#实体类用Pascal命名(Title/Text/Document)、前端传参用小驼峰/全小写都可以自动匹配,不需要特意对齐大小写。

备选方案(仅适用于小文件场景)

如果必须使用application/json格式提交,可以将文件转成Base64字符串后再做JSON序列化。但该方案会让文件体积增大约33%,大文件传输会严重占用带宽、拖慢接口响应速度,非必要不推荐使用。

前端修改点

先把选中的文件转成Base64字符串,再组装参数发起请求:

const selectedFile = $('#file').get(0).files[0];
const reader = new FileReader();
reader.onload = function(e) {
    const myProfile = {
        Title: "Lorem ipsum",
        Text: "Lorem ipsum",
        Document: {
            FileName: selectedFile.name,
            // 截掉base64前缀的data:MIME类型;base64, 部分,仅保留内容
            FileContent: e.target.result.split(',')[1]
        }
    };
    $.ajax({
        url: `/admin/myprofile`,
        type: "POST",
        data: JSON.stringify(myProfile),
        contentType: "application/json",
        dataType: 'json',
        success: function (res) {
            // 原有成功回调逻辑
        }
    });
}
reader.readAsDataURL(selectedFile);

后端修改点

调整Image类的属性类型,接收Base64反序列化后的字节数组:

public class Image
{
  public byte[] FileContent { get; set; }
  public string FileName { get; set; }
}

该方案需要额外在业务逻辑里把字节数组转成文件流做存储,比直接用IFormFile多一步处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 12:27:17