Aplikasi / x-www-form-urlencoded atau multipart / form-data?

Ada dua cara dalam HTTP untuk 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 . Apakah ada pedoman tambahan kapan menggunakan salah satu jenis penyandian dalam konteks API (tanpa keterlibatan browser)? Ini mungkin, misalnya, berdasarkan pada:

  • ukuran data
  • keberadaan karakter non-ASCII
  • keberadaan pada data biner (tanpa kode)
  • kebutuhan untuk mentransfer data tambahan (misalnya, nama file)

Pada dasarnya, saya tidak menemukan instruksi resmi di Internet mengenai penggunaan berbagai jenis konten.

935
24 окт. atur maksimal 24 Oktober. 2010-10-24 14:12 '10 pada 14:12 2010-10-24 14:12
@ 5 balasan

Tl; DR

Moral dari cerita ini adalah bahwa jika Anda memiliki data biner (non-alfanumerik) (atau muatan signifikan) untuk transmisi, gunakan data multipart/form-data . Jika tidak, gunakan application/x-www-form-urlencoded .


Tipe MIME yang dijelaskan adalah dua header Content-Type untuk permintaan HTTP POST yang harus didukung oleh agen pengguna (browser). Tujuan dari kedua pertanyaan ini adalah untuk mengirim daftar pasangan nama / nilai ke server. Bergantung pada jenis dan jumlah data yang ditransfer, satu metode akan lebih efisien daripada yang lain. Untuk memahami alasannya, Anda harus melihat apa yang dilakukan semua orang di bawah selimut.

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

MyVariableOne=ValueOne>

Sesuai dengan spesifikasi :

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

Ini berarti bahwa untuk setiap byte non-alfanumerik yang ada di salah satu nilai kami, dibutuhkan tiga byte untuk mewakilinya. Untuk binari besar, tiga kali lipat payload akan sangat tidak efisien.

Itu termasuk multipart/form-data . Menggunakan metode transmisi pasangan nama / nilai ini, setiap pasangan direpresentasikan sebagai “bagian” dalam pesan MIME (seperti yang dijelaskan dalam respons lain). Bagian-bagian dipisahkan oleh batas baris tertentu (dipilih dengan cara sedemikian rupa sehingga baris batas ini tidak terjadi pada muatan "berguna" apa pun). Setiap bagian memiliki set header MIME sendiri, seperti Content-Type , dan terutama Content-Disposition , yang dapat memberikan masing-masing bagian "nama". Elemen nilai dari setiap pasangan nama / nilai adalah muatan dari setiap bagian dari pesan MIME. Spesifikasi MIME memberi kita lebih banyak opsi saat menyajikan nilai payload - kita dapat memilih untuk menyandikan data biner secara lebih efisien untuk menghemat bandwidth (misalnya, basis 64 atau bahkan versi biner).

Mengapa tidak menggunakan multipart/form-data sepanjang waktu? Untuk nilai alfanumerik singkat (misalnya, sebagian besar formulir web), biaya tambahan untuk menambahkan semua header MIME melebihi penghematan apa pun dari pengkodean biner yang lebih efisien.

1475
02 нояб. Jawabannya diberikan oleh Matt Bridges 02 Nov. 2010-11-02 00:59 '10 pada 0:59 2010-11-02 00:59

BACA SETELAH PASANG PERTAMA DI SINI!

Saya tahu ini sudah 3 tahun, tetapi jawaban Matt (diterima) tidak lengkap dan pada akhirnya akan menimbulkan masalah. Poin kunci di sini adalah bahwa jika Anda memutuskan untuk menggunakan multipart/form-data , perbatasan seharusnya tidak muncul dalam file data yang akhirnya diterima oleh server.

Ini bukan masalah untuk application/x-www-form-urlencoded , karena tidak ada perbatasan. x-www-form-urlencoded juga selalu dapat menangani data biner hanya dengan mengubah satu byte sewenang-wenang menjadi tiga byte dari 7BIT . Itu tidak efisien, tetapi berfungsi (dan perhatikan bahwa komentar tentang ketidakmampuan untuk mengirim nama file, serta data biner salah, Anda cukup mengirimkannya sebagai pasangan kunci / nilai lain).

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

Jadi, sekilas, multipart/form-data tidak memiliki arti dalam pengunduhan file apa pun, dalam format biner atau lainnya. Jika Anda belum memilih perbatasan dengan benar, maka pada akhirnya Anda akan memiliki masalah, apakah Anda mengirim teks biasa atau file biner mentah - server akan menemukan perbatasan di tempat yang salah, dan file Anda akan terpotong, atau POST tidak akan berhasil.

Kunci harus memilih penyandian dan batas sehingga karakter batas yang dipilih tidak dapat ditampilkan dalam output kode. Salah satu solusi sederhana adalah dengan menggunakan base64 (jangan gunakan binari mentah). Dalam base64, 3 byte sewenang-wenang dikodekan menjadi empat karakter 7-bit, di mana himpunan karakter output adalah [A-Za-z0-9+/=] (misalnya, alfanumerik atau '+', '/', '/', '='). = adalah kasus khusus dan hanya dapat muncul di akhir output kode, sebagai satu = atau dua kali lipat == . Sekarang pilih perbatasan Anda sebagai string ASCII 7-bit yang tidak dapat ditampilkan dalam output base64 . Banyak opsi yang Anda lihat di jaringan tidak lulus tes ini - MDN bentuk dokumen , misalnya, menggunakan "gumpalan" sebagai perbatasan saat mengirim data kode biner tidak baik. Namun, sesuatu seperti "Gumpalan!" tidak pernah muncul dalam output base64 .

97
18 апр. jawabannya diberikan EML 18 Apr 2014-04-18 14:08 '14 pada 14:08 2014-04-18 14:08

Saya tidak berpikir HTTP terbatas pada POST di multipart atau x-www-form-urlencoded. Header dari Content-Type Header adalah ortogonal ke metode HTTP POST (Anda dapat mengisi tipe MIME yang cocok untuk Anda). Ini juga berlaku untuk aplikasi web berbasis HTML yang khas (misalnya, json payload telah menjadi sangat populer untuk mentransmisikan payload untuk permintaan ajax).

Sedangkan untuk Restful API over HTTP, jenis konten paling populer yang saya datangi adalah application / xml dan application / json.

aplikasi / xml:

  • ukuran data: XML sangat verbose, tetapi biasanya itu tidak masalah ketika menggunakan kompresi dan dianggap bahwa kasus akses tulis (misalnya, melalui POST atau PUT) jauh lebih jarang daripada akses baca (dalam banyak kasus itu sama dengan <3% dari semua lalu lintas) . Jarang sekali saya harus mengoptimalkan kinerja penulisan
  • keberadaan karakter non-ascii: Anda dapat menggunakan utf-8 sebagai penyandian dalam XML
  • keberadaan data biner: Anda harus menggunakan pengkodean base64
  • nama file data: Anda dapat merangkum bidang internal ini dalam XML

aplikasi / json

  • ukuran data: lebih kecil dari XML, teks diam, tetapi Anda dapat memampatkan
  • karakter non-ascii: json adalah utf-8
  • data biner: base64 (juga lihat json-binary-question )
  • filename: enkapsulasi sebagai bagian bidang Anda sendiri di dalam json

data biner sebagai sumber daya sendiri

Saya akan mencoba menyajikan data biner sebagai sumber daya saya sendiri. Dia menambahkan tantangan lain, tetapi lebih baik memisahkan materi. Contoh gambar:

 POST /images Content-type: multipart/mixed; boundary="xxxx" ... multipart data 201 Created Location: http://imageserver.org/../foo.jpg  POST /images Content-type: multipart/mixed; boundary="xxxx" ... multipart data 201 Created Location: http://imageserver.org/../foo.jpg 

Di sumber daya selanjutnya, Anda cukup memasukkan sumber daya biner sebagai referensi:

 <main-resource ... <link href="http://imageserver.org/../foo.jpg"/> </main-resource><main-resource ... <link href="http://imageserver.org/../foo.jpg"/> </main-resource> 
80
24 окт. balasan diberikan oleh manuel aldana 24 oct. 2010-10-24 19:46 '10 pada 19:46 2010-10-24 19:46

Saya setuju dengan apa yang dikatakan Manuel. Bahkan, komentarnya merujuk ke URL ini ...

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

... yang berbunyi:

Jenis konten "application / x-www-form-urlencoded" tidak efisien untuk mengirim sejumlah besar data biner atau teks yang mengandung karakter non-ASCII. Jenis konten "multipart / formulir-data" harus digunakan untuk mengirimkan formulir yang berisi data non-ASCII dan data biner.

Namun, bagi saya itu akan terhubung dengan dukungan alat / bingkai.

  • Alat dan kerangka apa yang Anda gunakan harapkan pengguna API Anda untuk membangun aplikasi mereka?
  • Apakah mereka memiliki kerangka kerja atau komponen yang dapat mereka gunakan yang berkontribusi pada satu metode yang lain?

Jika Anda memahami dengan jelas pengguna Anda dan bagaimana mereka akan menggunakan API Anda, ini akan membantu Anda memutuskan. Jika Anda mengunggah file untuk pengguna API Anda, mereka akan pergi dan Anda akan menghabiskan banyak waktu mendukungnya.

Sekunder dari ini akan menjadi alat pendukung yang Anda miliki untuk menulis API Anda, dan betapa mudahnya bagi Anda untuk menempatkan satu mekanisme pemuatan di atas yang lain.

24
27 окт. balasan yang diberikan oleh Martin Peck 27 Okt 2010-10-27 15:08 '10 pada 15:08 2010-10-27 15:08

Sedikit petunjuk pada saya untuk memuat data gambar kanvas HTML5:

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

Segera setelah saya mengatur versi contentType panggilan ajax jQuery saya ke application/x-www-form-urlencoded semuanya berjalan dengan benar, dan data yang disandikan dalam base64 ditafsirkan dengan benar dan berhasil disimpan sebagai gambar.


Mungkin itu membantu seseorang!

0
10 дек. jawab diberikan habaMedia 10 Des. 2015-12-10 18:07 '15 pada 18:07 2015-12-10 18:07

Pertanyaan lain tentang tag atau Ajukan Pertanyaan