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?

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.


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

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.