Pertanyaan aplikasi / x-www-form-urlencoded atau multipart / form-data?


Di HTTP, ada dua cara untuk mengirim data POST: application/x-www-form-urlencoded dan multipart/form-data. Saya mengerti bahwa sebagian besar browser hanya dapat mengunggah file jika multipart/form-data digunakan. Apakah ada panduan tambahan ketika menggunakan salah satu jenis pengkodean dalam konteks API (tidak ada browser yang terlibat)? Ini mungkin misalnya didasarkan pada:

  • ukuran data
  • keberadaan karakter non-ASCII
  • ada pada data biner (yang tidak dikodekan)
  • kebutuhan untuk mentransfer data tambahan (seperti nama file)

Saya pada dasarnya tidak menemukan panduan formal di web mengenai penggunaan jenis konten yang berbeda sejauh ini.


1066
2017-10-24 11:12


asal


Jawaban:


TL; DR

Ringkasan; jika Anda memiliki data biner (non-alfanumerik) (atau payload berukuran besar) untuk mengirim, gunakan multipart/form-data. Kalau tidak, gunakan application/x-www-form-urlencoded.


Jenis MIME yang Anda sebutkan adalah dua Content-Type header untuk permintaan HTTP POST yang harus didukung oleh agen pengguna (browser). Tujuan dari kedua jenis permintaan tersebut adalah untuk mengirim daftar pasangan nama / nilai ke server. Tergantung pada jenis dan jumlah data yang dikirim, salah satu metode akan lebih efisien daripada yang lain. Untuk memahami mengapa, Anda harus melihat apa yang dilakukan masing-masing di bawah selimut.

Untuk application/x-www-form-urlencoded, tubuh pesan HTTP yang dikirim ke server pada dasarnya adalah satu string permintaan raksasa - pasangan nama / nilai dipisahkan oleh ampersand (&), dan nama dipisahkan dari nilai oleh simbol yang sama (=). Contoh dari ini adalah:

MyVariableOne=ValueOne&MyVariableTwo=ValueTwo

Menurut spesifikasi:

[Dicadangkan dan] karakter non-alfanumerik diganti dengan `% HH ', tanda persen dan dua digit heksadesimal yang mewakili kode ASCII karakter

Itu berarti bahwa untuk setiap byte non-alfanumerik yang ada di salah satu nilai kami, itu akan mengambil tiga byte untuk mewakilinya. Untuk file biner yang besar, tiga kali lipat payload akan sangat tidak efisien.

Di situlah multipart/form-data masuk. Dengan metode transmisi pasangan nama / nilai ini, setiap pasangan direpresentasikan sebagai "bagian" dalam pesan MIME (seperti yang dijelaskan oleh jawaban lain). Bagian dipisahkan oleh batas string tertentu (dipilih secara khusus sehingga string batas ini tidak terjadi di salah satu payload "nilai"). Setiap bagian memiliki set header MIME sendiri seperti Content-Type, dan khususnya Content-Disposition, yang dapat memberikan masing-masing bagian "nama." Bagian nilai dari setiap pasangan nama / nilai adalah muatan dari setiap bagian dari pesan MIME. Spesifikasi MIME memberi kita lebih banyak pilihan ketika mewakili muatan nilai - kita dapat memilih pengkodean data biner yang lebih efisien untuk menghemat bandwidth (misalnya basis 64 atau bahkan biner mentah).

Mengapa tidak digunakan multipart/form-data sepanjang waktu? Untuk nilai alfanumerik pendek (seperti kebanyakan formulir web), biaya tambahan untuk menambahkan semua header MIME akan secara signifikan lebih besar daripada penghematan dari pengkodean biner yang lebih efisien.


1666
2017-11-01 21:59



BACA SETELAH PIRA PERTAMA DI SINI!

Saya tahu ini sudah 3 tahun terlambat, tetapi jawaban Matt (yang diterima) tidak lengkap dan akhirnya akan membuat Anda mendapat masalah. Kuncinya di sini adalah bahwa, jika Anda memilih untuk menggunakan multipart/form-data, batasnya harus tidak muncul dalam data file yang akhirnya diterima oleh server.

Ini bukan masalah bagi application/x-www-form-urlencoded, karena tidak ada batasan. x-www-form-urlencoded dapat juga selalu menangani data biner, dengan cara sederhana mengubah satu byte sewenang-wenang menjadi tiga 7BIT byte. Tidak efisien, tetapi berfungsi (dan perhatikan bahwa komentar tentang tidak dapat mengirim nama file serta data biner salah; Anda hanya mengirimnya sebagai pasangan kunci / nilai lain).

Masalah dengan multipart/form-data adalah bahwa pemisah batas tidak boleh ada dalam data file (lihat RFC2388; Bagian 5.2 juga termasuk alasan yang agak lemah karena tidak memiliki tipe MIME agregat yang tepat yang menghindari masalah ini).

Jadi, pada pandangan pertama, multipart/form-data tidak ada nilainya sama sekali apa saja upload file, biner atau sebaliknya. Jika Anda tidak memilih batasan Anda dengan benar, maka Anda akan akhirnya ada masalah, apakah Anda mengirim teks biasa atau biner mentah - server akan menemukan batasan di tempat yang salah, dan file Anda akan terpotong, atau POST akan gagal.

Kuncinya adalah memilih pengkodean dan batas sehingga karakter batas yang Anda pilih tidak dapat muncul dalam output yang dienkode. Satu solusi sederhana adalah menggunakan base64 (melakukan tidak gunakan biner mentah). Di base64 3 byte sewenang-wenang dikodekan menjadi empat karakter 7-bit, di mana set karakter output [A-Za-z0-9+/=] (mis. alfanumerik, atau '+', '/', '='). = adalah kasus khusus, dan mungkin hanya muncul di akhir output yang di-enkode, sebagai single = atau ganda ==. Sekarang, pilih batas Anda sebagai string ASCII 7-bit yang tidak dapat muncul base64 keluaran. Banyak pilihan yang Anda lihat di internet gagal dalam tes ini - MDN terbentuk dokumen, misalnya, gunakan "blob" sebagai batas saat mengirim data biner - tidak bagus. Namun, sesuatu seperti "! Blob!" tidak akan pernah muncul base64 keluaran.


106
2018-04-18 11:08



Saya tidak berpikir HTTP terbatas pada POST di multipart atau x-www-form-urlencoded. Itu Header Content-Type adalah orthogonal dengan metode HTTP POST (Anda dapat mengisi tipe MIME yang cocok untuk Anda). Ini juga berlaku untuk webapp berbasis representasi HTML yang khas (misalnya payload json menjadi sangat populer untuk mentransmisikan payload untuk permintaan ajax).

Mengenai Restful API over HTTP, jenis konten yang paling populer yang saya hubungi adalah aplikasi / xml dan aplikasi / json.

aplikasi / xml:

  • ukuran data: XML sangat verbose, tetapi biasanya tidak masalah ketika menggunakan kompresi dan berpikir bahwa kasus akses tulis (misalnya melalui POST atau PUT) jauh lebih jarang sebagai akses baca (dalam banyak kasus itu adalah <3% dari semua lalu lintas ). Jarang ada tempat di mana saya harus mengoptimalkan kinerja tulis
  • keberadaan karakter non-ascii: Anda dapat menggunakan utf-8 sebagai pengkodean dalam XML
  • keberadaan data biner: perlu menggunakan pengkodean base64
  • data nama file: Anda dapat mengenkapsulasi bidang di dalam ini dalam XML

aplikasi / json

  • ukuran data: lebih ringkas kurang XML itu, masih teks, tetapi Anda dapat memampatkan
  • non-ascii chars: json adalah utf-8
  • data biner: base64 (juga lihat pertanyaan json-biner)
  • data nama file: enkapsulasi sebagai bagian-kolom sendiri di dalam json

data biner sebagai sumber daya sendiri

Saya akan mencoba untuk merepresentasikan data biner sebagai aset / sumber daya sendiri. Ini menambah panggilan lain tetapi memisahkan hal-hal yang lebih baik. Gambar contoh:

POST /images
Content-type: multipart/mixed; boundary="xxxx" 
... multipart data

201 Created
Location: http://imageserver.org/../foo.jpg  

Dalam sumber daya selanjutnya, Anda bisa menyederhanakan sumber daya biner sebagai tautan:

<main-resource>
 ...
 <link href="http://imageserver.org/../foo.jpg"/>
</main-resource>

82
2017-10-24 16:46



Saya setuju dengan banyak hal yang dikatakan Manuel. Bahkan, komentarnya mengacu pada url ini ...

http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4

... yang menyatakan:

Jenis konten   "aplikasi / x-www-form-urlencoded" adalah   tidak efisien untuk mengirim besar   jumlah data biner atau teks   mengandung karakter non-ASCII. Itu   tipe konten "multipart / form-data"   harus digunakan untuk mengirimkan formulir   yang berisi file, data non-ASCII,   dan data biner.

Namun, bagi saya itu akan turun ke dukungan tool / framework.

  • Alat dan kerangka apa yang Anda miliki mengharapkan pengguna API Anda untuk membangun aplikasi mereka dengan?
  • Apakah mereka punya kerangka kerja atau komponen yang dapat mereka gunakan yang mendukung satu metode di atas lain?

Jika Anda mendapatkan gambaran yang jelas tentang pengguna Anda, dan bagaimana mereka akan menggunakan API Anda, maka itu akan membantu Anda memutuskan. Jika Anda membuat upload file sulit untuk pengguna API Anda maka mereka akan pindah, dari Anda akan menghabiskan banyak waktu untuk mendukung mereka.

Sekunder untuk ini adalah dukungan alat yang ANDA miliki untuk menulis API Anda dan betapa mudahnya bagi Anda untuk mengakomodasi satu mekanisme upload di atas yang lain.


26
2017-10-27 12:08



Hanya sedikit petunjuk dari pihak saya untuk mengunggah data gambar kanvas HTML5:

Saya sedang mengerjakan proyek untuk percetakan dan mengalami beberapa masalah karena mengunggah gambar ke server yang berasal dari HTML5 canvas elemen. Saya berjuang setidaknya selama satu jam dan saya tidak mendapatkannya untuk menyimpan gambar dengan benar di server saya.

Setelah saya mengatur contentType opsi panggilan jQuery ajax saya ke application/x-www-form-urlencoded semuanya berjalan dengan cara yang benar dan data base-encoded ditafsirkan dengan benar dan berhasil disimpan sebagai gambar.


Mungkin itu membantu seseorang!


0
2017-12-10 15:07