web-dev-qa-db-ja.com

方法POST multipart / form-dataヘッダーとfetchを使用したFormDataで

これは正常に機能するCURLの例です。

_curl -X POST \
  <url> \
  -H 'authorization: Bearer <token>' \
  -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
  -F [email protected] \
  -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
})`
_

fileに渡されるFormDataを生成するには、_fs.readFileSync_を使用します。

前の例は、トークンに埋め込まれた(ヘッダー経由で送信された)userIduserIdと一致しないというエラーメッセージを含む_401_ HTTPステータスコードを返します。 formData

だから、REST APIに到達するFormDataが適切に形成されていないのではないかと疑っています。

問題は_Content-Length_ヘッダーに関連している可能性がありますが、それを計算するより良い方法を見つけられませんでした(_Content-Length_ヘッダーを使用しない場合、_411_ HTTPステータスを取得します)コード_Content-Length_ヘッダーがありません)。

_Content-Length_ヘッダーの値が正しくないためにこれが失敗している可能性がありますか?

これが失敗する理由、またはデバッグ方法を改善する方法に関する他の提案はありますか?

この問題を明確にするためにさらに情報が必要な場合は、お問い合わせください。

[〜#〜] update [〜#〜]

メソッドformData.getLengthSync()を使用して正しい_Content-Length_値を取得するために form-data モジュールを試しました

ただし、問題は同じままです(_401_エラーHTTPステータスコード応答)。

6
rfc1484

ネットワークインスペクターを開いてこのコードスニペットを実行し、フォームを送信すると、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>

4
idbehold

特に、ノードで_isomorphic-fetch_を使用してPOST a multipart form。を見つけました。.getHeaders()を見つけることが重要でした。 _form-data_ の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}`);
}
_
2
Iain Bryson