Bagaimana cara melakukan POST dengan data formulir multi bagian menggunakan pengambilan?

90

Saya mengambil URL seperti ini:

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 saya mengharapkan datanya multipart/form-datajadi saya menggunakan content-typejenis ini ... Tapi itu memberi saya respons dengan kode status 400.

Apa yang salah dengan kode saya?

varad
sumber

Jawaban:

175

Anda menyetel Content-Typemenjadi multipart/form-data, tetapi kemudian menggunakan JSON.stringifydata tubuh, yang mengembalikan application/json. Anda memiliki jenis konten yang tidak cocok.

Anda perlu menyandikan data Anda sebagai multipart/form-datagantinya json. Biasanya multipart/form-datadigunakan saat mengupload file, dan sedikit lebih rumit daripada application/x-www-form-urlencoded(yang merupakan default untuk formulir HTML).

Spesifikasi multipart/form-datadapat ditemukan di RFC 1867 .

Untuk panduan tentang cara mengirimkan data semacam itu melalui javascript, lihat di sini .

Ide dasarnya adalah menggunakan objek FormData (tidak didukung di 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
  });

  // ...
}

Per artikel ini pastikan untuk tidak mengatur Content-Typeheader. Browser akan mengaturnya untuk Anda, termasuk boundaryparameternya.

rossipedia
sumber
const fd = new FormData (); // File untuk diunggah. fd.append ('file', fileToUpload); fd.append ('jsondatakey', 'jsondatavalue'); Dengan ini Anda akan dapat mengirim file bersama dengan beberapa data json di badan.
Jnana
Bagaimana jika saya membutuhkan Otorisasi?
DAVE
26

Saya baru-baru ini bekerja dengan IPFS dan menyelesaikannya. Contoh curl untuk IPFS untuk mengupload file terlihat seperti ini:

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"

Ide dasarnya adalah bahwa setiap bagian (dipisahkan dengan string boundarydengan --) memiliki headernya sendiri ( Content-Typedi bagian kedua, misalnya.) FormDataObjek mengatur semua ini untuk Anda, jadi ini cara yang lebih baik untuk mencapai tujuan kita.

Ini diterjemahkan untuk mengambil API seperti ini:

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)
})
konsumer
sumber
17
Catatan tentang metode di atas, JANGAN berikan header jika Anda melakukannya menggunakan FormData karena akan menimpa batas yang disetel secara otomatis.
Matt Pengelly
1
Terima kasih @MattPengelly! Bagaimana cara mengatur tajuk khusus seperti Otorisasi?
Dragos Strugar
7
@DragosStrugar Anda masih dapat mengatur header (termasuk Otorisasi), hanya saja jangan mengatur header Content-Type secara manual jika Anda menggunakan FormData.
RobertMcReed
3
JANGAN berikan header dengan 'Content-Type' jika menggunakan FormData.
caot
1
Dalam contoh curl, Anda membutuhkannya. Dalam FormDatacontoh, Anda tidak membutuhkannya, karena browser mengirimkan header itu untuk Anda & juga mengelola semua batas mime, yang merupakan inti dari solusi ini.
konsumer