Di HTTP ada dua cara untuk POST data: 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 kapan menggunakan salah satu jenis penyandian dalam konteks API (tidak ada browser yang terlibat)? Ini mungkin misalnya didasarkan pada:
- ukuran data
- keberadaan karakter non-ASCII
- keberadaan pada data biner (tidak ter-enkripsi)
- kebutuhan untuk mentransfer data tambahan (seperti nama file)
Saya pada dasarnya tidak menemukan panduan formal di web mengenai penggunaan tipe konten yang berbeda sejauh ini.
http
post
http-headers
maks
sumber
sumber
Jawaban:
TL; DR
Ringkasan; jika Anda memiliki data biner (non-alfanumerik) (atau muatan berukuran signifikan) untuk dikirim, gunakan
multipart/form-data
. Kalau tidak, gunakanapplication/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 alasannya, Anda harus melihat apa yang dilakukan masing-masing di bawah selimut.Sebab
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 dipisahkan dari nilai dengan simbol sama dengan (=
). Contohnya adalah:MyVariableOne=ValueOne&MyVariableTwo=ValueTwo
Sesuai dengan spesifikasi :
Itu berarti bahwa untuk setiap byte non-alfanumerik yang ada di salah satu nilai kami, dibutuhkan tiga byte untuk mewakilinya. Untuk file biner besar, tiga kali lipat payload akan menjadi sangat tidak efisien.
Di situlah
multipart/form-data
masuk. Dengan metode ini mentransmisikan pasangan nama / nilai, setiap pasangan direpresentasikan sebagai "bagian" dalam pesan MIME (seperti yang dijelaskan oleh jawaban lain). Bagian-bagian dipisahkan oleh batas string tertentu (dipilih secara khusus sehingga string batas ini tidak terjadi pada muatan "nilai" mana pun). Setiap bagian memiliki seperangkat header MIME sendiriContent-Type
, dan khususnyaContent-Disposition
, yang dapat memberi masing-masing bagian "nama". Sepotong nilai dari setiap pasangan nama / nilai adalah muatan dari setiap bagian dari pesan MIME. MIME spec memberi kita lebih banyak opsi saat mewakili nilai muatan - kita dapat memilih pengkodean data biner yang lebih efisien untuk menghemat bandwidth (mis. Basis 64 atau bahkan biner mentah).Kenapa tidak digunakan
multipart/form-data
sepanjang waktu? Untuk nilai alfanumerik singkat (seperti kebanyakan formulir web), biaya tambahan untuk menambahkan semua header MIME akan secara signifikan lebih besar daripada penghematan dari pengkodean biner yang lebih efisien.sumber
BACA SETIDAKNYA PARA PERTAMA DI SINI!
Saya tahu ini terlambat 3 tahun, tetapi jawaban Matt (diterima) tidak lengkap dan pada akhirnya akan membuat Anda kesulitan. Kuncinya di sini adalah, jika Anda memilih untuk menggunakan
multipart/form-data
, batas tidak boleh muncul dalam data file yang akhirnya diterima server.Ini bukan masalah bagi
application/x-www-form-urlencoded
, karena tidak ada batasan.x-www-form-urlencoded
juga dapat selalu menangani data biner, dengan cara sederhana mengubah satu byte sewenang-wenang menjadi tiga7BIT
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).Masalahnya
multipart/form-data
adalah bahwa pemisah batas tidak boleh ada dalam data file (lihat RFC 2388 ; bagian 5.2 juga mencakup alasan yang agak timpang karena tidak memiliki tipe MIME agregat yang tepat yang menghindari masalah ini).Jadi, pada pandangan pertama,
multipart/form-data
tidak ada nilai sama sekali dalam file apa pun , biner atau lainnya. Jika Anda tidak memilih batas dengan benar, maka pada akhirnya Anda akan memiliki masalah, apakah Anda mengirim teks biasa atau biner mentah - server akan menemukan batas 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 disandikan. Salah satu solusi sederhana adalah dengan menggunakan
base64
(jangan tidak menggunakan biner mentah). Dalam base64 3 byte acak dikodekan menjadi empat karakter 7-bit, di mana himpunan karakter keluarannya[A-Za-z0-9+/=]
(yaitu alfanumerik, '+', '/' atau '=').=
adalah kasus khusus, dan hanya dapat muncul di akhir output yang disandikan, sebagai tunggal=
atau ganda==
. Sekarang, pilih batas Anda sebagai string ASCII 7-bit yang tidak dapat muncul dalambase64
output. Banyak pilihan yang Anda lihat di internet gagal dalam tes ini - MDN membentuk dokumen, misalnya, gunakan "gumpalan" sebagai batas saat mengirim data biner - tidak baik. Namun, sesuatu seperti "gumpalan!" tidak akan pernah muncul dalambase64
output.sumber
index === -1
.'()+-./:=
itu. Namun generasi acak dengan substring cek masih merupakan cara untuk pergi dan itu bisa dilakukan dengan satu baris:while(true){r = rand(); if(data.indexOf(r) === -1){doStuff();break;}}
. Saran EML (konversi ke base64 hanya untuk menghindari substring yang cocok) benar-benar aneh, belum lagi disertai dengan penurunan kinerja yang tidak dibutuhkan. Dan semua masalah tidak ada karena algoritma satu baris sama mudah dan sederhana. Base64 tidak dimaksudkan untuk digunakan (ab) dengan cara ini, karena badan HTTP menerima semua oktet 8-bit .Saya tidak berpikir HTTP terbatas pada POST di multi-bagian atau x-www-form-urlencoded. The Content-Type header adalah orthogonal dengan metode HTTP POST (Anda dapat mengisi tipe MIME yang cocok untuk anda). Ini juga merupakan kasus untuk webapps berbasis representasi HTML (mis. Json payload menjadi sangat populer untuk mentransmisikan payload untuk permintaan ajax).
Mengenai Restful API over HTTP, tipe konten paling populer yang saya hubungi adalah application / xml dan application / json.
aplikasi / xml:
aplikasi / json
data biner sebagai sumber daya sendiri
Saya akan mencoba untuk mewakili data biner sebagai aset / sumber daya sendiri. Itu menambah panggilan lain tetapi memisahkan hal-hal yang lebih baik. Contoh gambar:
Di sumber daya yang lebih baru Anda bisa dengan mudah menyejajarkan sumber daya biner sebagai tautan:
sumber
Saya setuju dengan banyak hal yang dikatakan Manuel. Bahkan, komentarnya merujuk ke url ini ...
http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4
... yang menyatakan:
Namun, bagi saya itu akan turun ke dukungan alat / kerangka kerja.
Jika Anda mendapatkan gagasan yang jelas tentang pengguna Anda, dan bagaimana mereka akan menggunakan API Anda, maka itu akan membantu Anda memutuskan. Jika Anda membuat unggahan file menjadi sulit bagi pengguna API Anda maka mereka akan pindah, karena Anda akan menghabiskan banyak waktu untuk mendukungnya.
Yang kedua dari hal ini adalah dukungan alat yang Anda miliki untuk menulis API Anda dan betapa mudahnya bagi Anda untuk mengakomodasi satu mekanisme unggahan di atas yang lain.
sumber
Hanya sedikit petunjuk dari pihak saya untuk mengunggah data gambar kanvas HTML5:
Saya sedang mengerjakan proyek untuk toko cetak dan memiliki beberapa masalah karena mengunggah gambar ke server yang berasal dari
canvas
elemen HTML5 . Saya berjuang setidaknya selama satu jam dan saya tidak mendapatkannya untuk menyimpan gambar dengan benar di server saya.Setelah saya mengatur
contentType
opsi panggilan ajax jQuery saya untukapplication/x-www-form-urlencoded
semuanya berjalan dengan benar dan data base64-encoded ditafsirkan dengan benar dan berhasil disimpan sebagai gambar.Mungkin itu membantu seseorang!
sumber
Jika Anda perlu menggunakan Content-Type = x-www-urlencoded-form maka JANGAN gunakan FormDataCollection sebagai parameter: Di asp.net Core 2+ FormDataCollection tidak memiliki konstruktor default yang diperlukan oleh Formatters. Gunakan IFormCollection sebagai gantinya:
sumber