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

如何正确获取FormData文件数据并通过Ajax提交?

问题:表单上传文件时Ajax无法提交完整文件数据

我开发了一个允许用户同时上传音频文件和图片文件的表单,但测试时发现alert仅返回基础数据,未包含文件信息,文件字段显示为{}。想了解如何确保通过Ajax请求提交完整的文件数据。

前端React代码

function PodcastUpload({ data }) {
  
  function handleSubmit(e) {
    e.preventDefault();
    const formData = new FormData(document.getElementById("podcastupload"));
    
   var json =  JSON.stringify(Object.fromEntries(formData.entries()));

    alert(json);
    console.log('You clicked submit.');
  }


    return (<>
        <h1>Upload New Episode</h1>
        <h2>{data}</h2>
        <form id="podcastupload" onSubmit={handleSubmit} >

          <input type="file" id="file" name="file" multiple></input>
          <input name="uuid" value="62569301efd5e89879d13b29"/>
          <input name="show_id" value="617414548b226e7231bfba5b"/>
          <input name="show_b" value="proptech"/>
          <input name="season" value="4"/>
          <input name="episode_no" value="40"/>
          <input name="title" value="test title"/>
          <textarea name="description"></textarea>
          <input name="explicit" value="false"/>
          <input type="date" name="pubDate"/>
          
          <input type="submit"/>
        </form>
    </>)

}

Alert返回结果

{"file":{},"uuid":"62569301efd5e89879d13b29","show_id":"617414548b226e7231bfba5b","show_b":"proptech","season":"4","episode_no":"40","title":"test title","description":"","explicit":"false","pubDate":"2022-09-08"}

Postman生成的后端请求示例代码

var request = require('request');
var fs = require('fs');
var options = {
  'method': 'POST',
  'url': 'http://localhost:3000/api/podcasts/gupload',
  'headers': {
    'Cookie': 'next-auth.session-token=eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..OWf8yhLsBihBAl3N.EMeo_KcosE6QlogUi22Kps6z3lyeyQlk3vP9lNdyvlqDaA8SKOXJtpv3cfrAIVMn7CaBcLDKysAIy3KAFYWCYyFg3hpzwh6yNkTTn65Y_ktuH-N0u_sUCQ1i_dhhVTUHK-q3ck6ttzPIsfD_9YogHWj4ha2GaO72ukMval_7P8CN9OVt0ZBmBCbjyQY-UoZCeFi9qRRac994ReHy_oRUPeF3Cbv-4Nrm9G3MtK1A2X25YIRlDowiehQwFUU_8Kb1fcaEzFE.rm3d-QIASavADhiMmBqqzQ'
  },
  formData: {
    'file': {
      'value': fs.createReadStream('/Users/russellharrower/Downloads/S04E02.png'),
      'options': {
        'filename': 'S04E02.png',
        'contentType': null
      }
    },
    'file': {
      'value': fs.createReadStream('/Users/russellharrower/Desktop/S04E02.mp3'),
      'options': {
        'filename': 'S04E02.mp3',
        'contentType': null
      }
    },
    'uuid': '62569301efd5e89879d13b29',
    'show_id': '617414548b226e7231bfba5b',
    'show_b': 'Test',
    'season': '4',
    'episode_no': '2',
    'title': 'Test',
    'description': '<pTest</p>',
    'explicit': 'false',
    'pubDate': '2022-09-25T14:00:00+08:00'
  }
};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

解决方案

1. 问题根源

你看到file字段显示为{},是因为File对象无法被JSON.stringify正确序列化——JSON只能处理基础类型,文件这类二进制对象转JSON后就变成空对象了。但实际上FormData对象里已经正确包含了文件数据,只是你转成JSON后看不到而已。

2. 正确的Ajax提交方式

不要将FormData转成JSON,直接发送FormData对象即可,浏览器会自动处理multipart/form-data格式的请求:

使用fetch的修改示例:

function handleSubmit(e) {
  e.preventDefault();
  const formData = new FormData(document.getElementById("podcastupload"));

  // 直接发送FormData,无需转JSON
  fetch('http://localhost:3000/api/podcasts/gupload', {
    method: 'POST',
    credentials: 'include', // 自动携带登录Cookie,对应Postman里的Cookie头
    body: formData
  })
  .then(response => {
    if (!response.ok) throw new Error('请求失败');
    return response.json();
  })
  .then(result => {
    console.log('上传成功:', result);
    // 这里可以做成功后的提示或跳转
  })
  .catch(err => {
    console.error('上传出错:', err);
  });
}

使用axios的修改示例(如果项目用axios):

import axios from 'axios';

function handleSubmit(e) {
  e.preventDefault();
  const formData = new FormData(document.getElementById("podcastupload"));

  axios.post('http://localhost:3000/api/podcasts/gupload', formData, {
    withCredentials: true, // 携带Cookie
    // 不需要手动设置Content-Type,axios会自动添加正确的multipart/form-data及boundary
  })
  .then(response => {
    console.log('上传成功:', response.data);
  })
  .catch(error => {
    console.error('上传出错:', error);
  });
}

3. 关键注意事项

  • 你的文件输入已经设置了multiple,可以选择多个文件,FormData会自动将多个文件以同名file字段的形式提交,和Postman示例的格式一致,后端能正确接收。
  • 不要手动设置Content-Type: multipart/form-data,浏览器或axios会自动添加包含boundary的正确头信息,手动设置反而会导致请求格式错误。
  • 如果需要携带登录状态的Cookie,要设置credentials: 'include'(fetch)或withCredentials: true(axios)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 06:55:19