11

这是一个运行良好的 CURL 示例:

curl -X POST \
  <url> \
  -H 'authorization: Bearer <token>' \
  -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
  -F file=@algorithm.jpg \
  -F userId=<userId>

我正在尝试使用isomorphic-fetch重现此请求。

我试过以下代码:

const formData = new FormData();
formData.append('file', file);
formData.append('userId', userId);

return fetch(`<url>`, {      
  method: 'POST',
  headers: {
    'Content-Length': file.length
    'Authorization: Bearer <authorization token>',
    'Content-Type': 'multipart/form-data'
  },
  body: formData
})`

我使用fs.readFileSync以生成file传递给FormData.

前面的示例返回一个401HTTP 状态代码(未经授权),并带有一条错误消息,指出嵌入在令牌中(通过标头发送)与传递的 fromuserId不匹配。userIdformData

所以我怀疑FormData到达 REST API 的那个没有充分形成。

问题可能与Content-Length标头有关,但我没有找到更好的计算方法(如果我不使用Content-Length标头,我会收到411HTTP 状态代码Content-Length标头丢失)。

可能是由于Content-Length标头中的值不正确而导致失败的情况?

关于为什么失败或如何更好地调试它的任何其他建议?

如果需要进一步的信息来澄清这个问题,请询问。

更新

我已经尝试了表单数据模块,以便Content-Length使用该方法获得正确的值formData.getLengthSync()

但是问题仍然存在(401错误 HTTP 状态代码响应)。

4

2 回答 2

9

如果你打开你的网络检查器,运行这个代码片段,然后提交你应该看到Content-Length设置正确的表单:

const foo = document.getElementById('foo')
foo.addEventListener('submit', (e) => {
  e.preventDefault()
  const formData = new FormData(foo)
  formData.append('userId', 123)
  fetch('//example.com', {
    method: 'POST',
    body: formData
  })
})
<form id="foo">
  <input id="file" type="file" name="file"/><br><br>
  <button type="submit">Submit</button>
</form>

于 2017-04-20T13:31:59.383 回答
7

我把头撞到了类似的墙上,特别是isomorphic-fetch在节点上使用 POST 多部分表单。对我来说,关键是找到.getHeaders(). 请注意,对于NPM 的描述form-data表明,如果没有这个,它会“正常工作”,但它似乎没有,至少在节点中没有(我认为浏览器会注入标头内容?)。

// image is a Buffer containing a PNG image
// auth is the authorization token

const form_data  = new FormData();
form_data.append("image", png, {
    filename: `image.png`,
    contentType: 'application/octet-stream',
    mimeType: 'application/octet-stream'
});

const headers = Object.assign({
    'Accept': 'application/json',
    'Authorization': auth,
}, form_data.getHeaders());

try {
    const image_res = await fetch(url, {
        method: 'POST',
        headers: headers,
        body: form_data
    });

    if (!image_res.ok) {
        const out = await image_res.json();
        console.dir(out);
        return;
    }
}
catch (e) {
    console.error(`Chart image generation exception: ${e}`);
}
于 2018-04-10T00:20:24.667 回答