如何使用fetch来发布多部分/表单数据头和表单数据

时间:2022-10-22 20:33:08

This is a CURL example which works fine:

这是一个很好的旋度例子:

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

I'm trying to reproduce this request using isomorphic-fetch.

我正在尝试使用同形取回复制这个请求。

I've tried the following code:

我试过以下代码:

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
})`

I use fs.readFileSync in order to generate the file passed to FormData.

我使用fs。为了生成传递给FormData的文件而读取filesync。

The previous example returns a 401 HTTP status code (unauthorized) with an error message saying that the userId embedded in the token (sent via header) does not match the userId passed from formData.

前面的示例返回一个401 HTTP状态码(未授权的),其中有一条错误消息说嵌入在令牌中的userId(通过header发送)与从formData传递的userId不匹配。

So my suspicion is that the FormData that arrives to the REST API is not adequately formed.

因此我怀疑到达REST API的FormData没有得到充分的格式。

The problem may be related with the Content-Length header, but I didn't find a better way to calculate it (if I don't use the Content-Length header I get a 411 HTTP status code Content-Length header missing).

这个问题可能与内容长度头有关,但是我没有找到更好的方法来计算它(如果我不使用内容长度头,我将得到一个411 HTTP状态码内容长度头丢失)。

Could be the case that this is failing because of an incorrect value in the Content-Length header?

可能是因为在内容长度标题中有错误的值而导致失败的情况?

Any other suggestions on why this is failing or how to better debug it?

关于为什么会失败或者如何更好地调试它,还有其他建议吗?

If further info is needed to clarify this problem, please just ask.

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

UPDATE

更新

I've tried the form-data module in order to get the right Content-Length value using the method formData.getLengthSync()

为了使用formData.getLengthSync()方法获取正确的内容长度值,我尝试了form-data模块

However the problem remains the same (401 error HTTP status code response).

但是问题仍然是一样的(401错误HTTP状态码响应)。

2 个解决方案

#1


2  

If you open up your network inspector, run this code snippet, and submit the form you should see that the Content-Length is set correctly:

如果打开网络检查器,运行此代码片段,并提交表单,您将看到内容长度设置正确:

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>

如何使用fetch来发布多部分/表单数据头和表单数据

#2


2  

I hit my head against a similar wall, specifically using isomorphic-fetch on node to POST a multipart form. The key for me was finding .getHeaders(). Note that NPM description for form-data suggests that it'll "just work" without this, but it doesn't seem to, at least not in node (I think browsers inject header stuff?).

我的头碰到了一个类似的墙,特别是使用在节点上的异构获取来发布一个多部分的表单。对我来说,关键是找到。getheaders()。注意,对于表单-数据的NPM描述表明,如果没有它,它将“只工作”,但它似乎不工作,至少在节点中不工作(我认为浏览器会注入头信息?)

// 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}`);
}

#1


2  

If you open up your network inspector, run this code snippet, and submit the form you should see that the Content-Length is set correctly:

如果打开网络检查器,运行此代码片段,并提交表单,您将看到内容长度设置正确:

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>

如何使用fetch来发布多部分/表单数据头和表单数据

#2


2  

I hit my head against a similar wall, specifically using isomorphic-fetch on node to POST a multipart form. The key for me was finding .getHeaders(). Note that NPM description for form-data suggests that it'll "just work" without this, but it doesn't seem to, at least not in node (I think browsers inject header stuff?).

我的头碰到了一个类似的墙,特别是使用在节点上的异构获取来发布一个多部分的表单。对我来说,关键是找到。getheaders()。注意,对于表单-数据的NPM描述表明,如果没有它,它将“只工作”,但它似乎不工作,至少在节点中不工作(我认为浏览器会注入头信息?)

// 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}`);
}