使用多部分表单数据获取帖子

ary*_*yan 65 javascript fetch fetch-api

我正在获取这样的URL:

fetch(url, {
  mode: 'no-cors',
  method: method || null,
  headers: {
    'Accept': 'application/json, application/xml, text/plain, text/html, *.*',
    'Content-Type': 'multipart/form-data'
  },
  body: JSON.stringify(data) || null,
}).then(function(response) {
  console.log(response.status)
  console.log("response");
  console.log(response)
})
Run Code Online (Sandbox Code Playgroud)

我的API期望数据是multipart/form-data这样的,我正在使用content-type这种类型......但是它给了我一个状态代码为400的响应.

我的代码出了什么问题?

ros*_*dia 117

你设置Content-Typemultipart/form-data,但是如果使用JSON.stringify对身体的数据,它返回application/json.您的内容类型不匹配.

您需要将数据编码为multipart/form-data而不是json.通常multipart/form-data在上传文件时使用,并且比复杂application/x-www-form-urlencoded(这是HTML表单的默认设置)要复杂一些.

规范multipart/form-data可以在RFC 1867中找到.

有关如何通过javascript提交此类数据的指南,请参阅此处.

基本思想是使用FormData对象(IE <10不支持):

async function sendData(url, data) {
  const formData  = new FormData();

  for(const name in data) {
    formData.append(name, data[name]);
  }

  const response = await fetch(url, {
    method: 'POST',
    body: formData
  });

  // ...
}
Run Code Online (Sandbox Code Playgroud)

  • const fd = new FormData(); // 要上传的文件。fd.append('文件', fileToUpload); fd.append('jsondatakey', 'jsondatavalue'); 这样您就可以发送文件以及正文中的一些 json 数据。 (6认同)
  • 如果我需要授权怎么办? (6认同)
  • 像这样的事情就可以做到: { method: 'POST', headers: { 'Authorization': 'Bearer ' + token }, body: formData } (2认同)

kon*_*mer 16

我最近在与IPFS合作并解决了这个问题.IPFS上传文件的curl示例如下所示:

curl -i -H "Content-Type: multipart/form-data; boundary=CUSTOM" -d $'--CUSTOM\r\nContent-Type: multipart/octet-stream\r\nContent-Disposition: file; filename="test"\r\n\r\nHello World!\n--CUSTOM--' "http://localhost:5001/api/v0/add"
Run Code Online (Sandbox Code Playgroud)

其基本思路是,每个部分(由字符串分割boundary--),有它自己的头(Content-Type在第二部分,例如)的FormData对象管理这一切给你,所以这是一个更好的方式来实现我们的目标.

这转换为获取API,如下所示:

const formData = new FormData()
formData.append('blob', new Blob(['Hello World!\n']), 'test')

fetch('http://localhost:5001/api/v0/add', {
  method: 'POST',
  body: formData
})
.then(r => r.json())
.then(data => {
  console.log(data)
})
Run Code Online (Sandbox Code Playgroud)

  • 关于上述方法的注意事项,如果使用FormData执行此操作,请不要提供标题,因为它将覆盖自动设置的边界. (11认同)
  • 在卷曲示例中,您需要它。在“FormData”示例中,您不需要它,因为浏览器会为您发送该标头并管理所有 mime 边界,这是此解决方案的重点。 (4认同)
  • @DragosStrugar,您仍然可以设置标题(包括授权),如果您使用的是FormData,请不要手动设置Content-Type标题。 (3认同)
  • 谢谢@MattPengelly!那么如何设置像 Authorization 这样的自定义标头呢? (2认同)
  • 如果使用的是FormData,请不要提供“ Content-Type”标题。 (2认同)
  • @Brian Peterson:我同意。即使您有其他信息要添加,也不算太糟糕:每个其他值的 formData.set("field","value") (在循环中执行)。 (2认同)