フェッチを使用してマルチパートフォームデータでPOSTするにはどうすればよいですか?


90

私は次のような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)
})

私のAPIはデータがであると想定しているmultipart/form-dataのでcontent-type、このタイプを使用しています...しかし、ステータスコード400の応答が返されます。

私のコードの何が問題になっていますか?

回答:


176

をに設定しContent-Typeていますmultipart/form-dataJSON.stringify、本文データを使用すると、が返されますapplication/json。コンテンツタイプが一致しません。

multipart/form-data代わりにとしてデータをエンコードする必要がありますjson。通常multipart/form-data、ファイルをアップロードするときに使用され、application/x-www-form-urlencoded(HTMLフォームのデフォルト)よりも少し複雑です。

の仕様multipart/form-dataRFC1867にあります

この種のデータを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
  });

  // ...
}

この記事に従って、ヘッダーを設定しないようにしてくださいContent-Type。ブラウザがboundaryパラメータを含めて設定します。


const fd = new FormData(); //アップロードするファイル。fd.append( 'file'、fileToUpload); fd.append( 'jsondatakey'、 'jsondatavalue'); これにより、jsonデータと一緒にファイルを本文で送信できるようになります。
ジュナナ

承認が必要な場合はどうなりますか?
DAVE

26

私は最近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"

基本的な考え方は、各パート(内の文字列によって分割さという点である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)
})

17
上記の方法については、FormDataを使用して行う場合は、自動的に設定される境界を上書きするため、ヘッダーを指定しないでください。
マットペンゲリー2018

1
ありがとう@MattPengelly!では、Authorizationのようなカスタムヘッダーを設定するにはどうすればよいですか?
DragosStrugar19年

7
@DragosStrugarでもヘッダー(承認を含む)を設定できます。FormDataを使用している場合は、Content-Typeヘッダーを手動で設定しないでください。
RobertMcReed

3
FormDataを使用している場合は、ヘッダーに「Content-Type」を指定しないでください。
caot

1
カールの例では、それが必要です。このFormData例では、ブラウザがそのヘッダーを送信し、すべてのmime-boundriesも管理するため、これは必要ありません。これがこのソリューションのポイントです。
konsumer
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.