Jawaban:
Saat Anda membuat permintaan POST, Anda harus menyandikan data yang membentuk badan permintaan dengan beberapa cara.
Formulir HTML menyediakan tiga metode pengkodean.
application/x-www-form-urlencoded
(default)multipart/form-data
text/plain
Pekerjaan sedang dilakukan untuk menambah application/json
, tetapi itu telah ditinggalkan.
(Penyandian lain dimungkinkan dengan permintaan HTTP yang dihasilkan menggunakan cara lain selain pengiriman formulir HTML. JSON adalah format umum untuk digunakan dengan layanan web dan beberapa masih menggunakan SOAP.)
Spesifikasi format tidak penting bagi sebagian besar pengembang. Poin-poin penting adalah:
text/plain
.Saat Anda menulis kode sisi klien:
multipart/form-data
saat formulir Anda menyertakan <input type="file">
elemen apa punmultipart/form-data
atau application/x-www-form-urlencoded
tetapi application/x-www-form-urlencoded
akan lebih efisienSaat Anda menulis kode sisi server:
Sebagian besar (seperti Perl CGI->param
atau yang diekspos oleh $_POST
superglobal PHP ) akan menangani perbedaan untuk Anda. Jangan repot-repot mencoba mengurai input mentah yang diterima oleh server.
Terkadang Anda akan menemukan perpustakaan yang tidak bisa menangani kedua format. Pustaka Node.js yang paling populer untuk menangani data formulir adalah body-parser yang tidak bisa menangani permintaan multi-bagian (tetapi memiliki dokumentasi yang merekomendasikan beberapa alternatif yang bisa).
Jika Anda menulis (atau men-debug) pustaka untuk parsing atau menghasilkan data mentah, maka Anda perlu mulai mengkhawatirkan formatnya. Anda mungkin juga ingin mengetahuinya demi kepentingan.
application/x-www-form-urlencoded
kurang lebih sama dengan string kueri di akhir URL.
multipart/form-data
secara signifikan lebih rumit tetapi memungkinkan seluruh file untuk dimasukkan dalam data. Contoh hasilnya dapat ditemukan dalam spesifikasi HTML 4 .
text/plain
diperkenalkan oleh HTML 5 dan hanya bermanfaat untuk debugging - dari spesifikasi : Mereka tidak dapat ditafsirkan secara andal oleh komputer - dan saya berpendapat bahwa yang lain digabungkan dengan alat (seperti Panel Jaringan pada alat pengembang sebagian besar peramban) lebih baik untuk itu).
kapan kita harus menggunakannya
Jawaban Quentin benar: gunakan multipart/form-data
jika formulir berisi unggahan file, dan application/x-www-form-urlencoded
sebaliknya, yang merupakan default jika Anda hilangkan enctype
.
Saya akan:
Ada tiga kemungkinan untuk enctype
:
application/x-www-form-urlencoded
multipart/form-data
(poin spesifik ke RFC7578 )text/plain
. Ini "tidak dapat diartikan secara andal oleh komputer", jadi tidak boleh digunakan dalam produksi, dan kita tidak akan melihat lebih jauh ke dalamnya.Setelah Anda melihat contoh masing-masing metode, menjadi jelas bagaimana cara kerjanya, dan kapan Anda harus menggunakannya.
Anda dapat menghasilkan contoh menggunakan:
nc -l
atau server ECHO: server uji HTTP yang menerima permintaan GET / POSTSimpan formulir ke .html
file minimal :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>upload</title>
</head>
<body>
<form action="http://localhost:8000" method="post" enctype="multipart/form-data">
<p><input type="text" name="text1" value="text default">
<p><input type="text" name="text2" value="aωb">
<p><input type="file" name="file1">
<p><input type="file" name="file2">
<p><input type="file" name="file3">
<p><button type="submit">Submit</button>
</form>
</body>
</html>
Kami menetapkan nilai teks default aωb
, yang berarti aωb
karena ω
merupakan U+03C9
, yang merupakan byte 61 CF 89 62
dalam UTF-8.
Buat file untuk diunggah:
echo 'Content of a.txt.' > a.txt
echo '<!DOCTYPE html><title>Content of a.html.</title>' > a.html
# Binary file containing 4 bytes: 'a', 1, 2 and 'b'.
printf 'a\xCF\x89b' > binary
Jalankan server gema kecil kami:
while true; do printf '' | nc -l 8000 localhost; done
Buka HTML di browser Anda, pilih file dan klik kirim dan periksa terminal.
nc
mencetak permintaan yang diterima.
Diuji pada: Ubuntu 14.04.3, nc
BSD 1.105, Firefox 40.
Firefox mengirim:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
Content-Length: 834
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text1"
text default
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text2"
aωb
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain
Content of a.txt.
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html
<!DOCTYPE html><title>Content of a.html.</title>
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file3"; filename="binary"
Content-Type: application/octet-stream
aωb
-----------------------------735323031399963166993862150--
Untuk file biner dan bidang teks, byte 61 CF 89 62
( aωb
dalam UTF-8) dikirim secara harfiah. Anda dapat memverifikasi itu dengan nc -l localhost 8000 | hd
, yang mengatakan bahwa byte:
61 CF 89 62
dikirim ( 61
== 'a' dan 62
== 'b').
Karena itu jelas bahwa:
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
mengatur jenis konten multipart/form-data
dan mengatakan bahwa bidang dipisahkan oleh boundary
string yang diberikan .
Tetapi perhatikan bahwa:
boundary=---------------------------735323031399963166993862150
memiliki dua ayah kurang --
dari penghalang yang sebenarnya
-----------------------------735323031399963166993862150
Ini karena standar mengharuskan batas untuk memulai dengan dua tanda hubung --
. Tanda hubung lainnya tampaknya hanya bagaimana Firefox memilih untuk menerapkan batas arbitrer. RFC 7578 dengan jelas menyebutkan bahwa kedua tanda hubung utama --
diperlukan:
4.1. "Batas" Parameter multipart / formulir-data
Seperti jenis multi bagian lainnya, bagian-bagian dibatasi dengan pembatas batas, dibangun menggunakan CRLF, "-", dan nilai parameter "batas".
setiap bidang mendapat beberapa sub header sebelum data: Content-Disposition: form-data;
, bidang name
, yang filename
, diikuti oleh data.
Server membaca data hingga string batas berikutnya. Peramban harus memilih batas yang tidak akan muncul di bidang mana pun, jadi inilah sebabnya batas mungkin berbeda di antara permintaan.
Karena kami memiliki batas unik, tidak diperlukan penyandian data: data biner dikirim apa adanya.
TODO: berapakah ukuran batas optimal ( log(N)
saya yakin), dan nama / waktu berjalan dari algoritma yang menemukannya? Ditanya di: /cs/39687/find-the-shortest- berikutnyaence-that-is-not-a-sub- berikutnyaence- of-a- set- of- afterences
Content-Type
ditentukan secara otomatis oleh browser.
Bagaimana ditentukan dengan tepat ditanyakan di: Bagaimana jenis mime dari file yang diunggah ditentukan oleh browser?
Sekarang ubah enctype
ke application/x-www-form-urlencoded
, muat ulang peramban, dan kirim kembali.
Firefox mengirim:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: application/x-www-form-urlencoded
Content-Length: 51
text1=text+default&text2=a%CF%89b&file1=a.txt&file2=a.html&file3=binary
Jelas data file tidak dikirim, hanya nama dasarnya. Jadi ini tidak dapat digunakan untuk file.
Adapun bidang teks, kita melihat bahwa karakter yang dapat dicetak biasa seperti a
dan b
dikirim dalam satu byte, sedangkan yang non-printable seperti 0xCF
dan 0x89
mengambil 3 byte masing-masing: %CF%89
!
Unggahan file sering mengandung banyak karakter yang tidak dapat dicetak (mis. Gambar), sedangkan bentuk teks hampir tidak pernah dilakukan.
Dari contoh-contoh yang telah kita lihat bahwa:
multipart/form-data
: menambahkan beberapa byte batas overhead ke pesan, dan harus meluangkan waktu untuk menghitungnya, tetapi mengirimkan setiap byte dalam satu byte.
application/x-www-form-urlencoded
: memiliki batas byte tunggal per bidang ( &
), tetapi menambahkan faktor overhead linier 3x untuk setiap karakter yang tidak dapat dicetak.
Oleh karena itu, bahkan jika kami dapat mengirim file application/x-www-form-urlencoded
, kami tidak akan mau, karena sangat tidak efisien.
Tetapi untuk karakter yang dapat dicetak ditemukan di bidang teks, itu tidak masalah dan menghasilkan lebih sedikit overhead, jadi kami hanya menggunakannya.
%CF
adalah 3 byte panjang: %
, C
dan F
:-) Kisah sehingga dapat dibaca manusia.
nc
tidak akan menerima baik -l
dan -p
argumen secara bersamaan. Tapi ini bekerja untuk saya: while true; do printf '' | nc -l 8000; done
.
Content-Type
memiliki dua tanda hubung ( --
) lebih sedikit, yaitu ketika benar-benar menggunakan batas dalam badan pesan, Anda harus mengawalinya dengan --
. Juga, batas terakhir harus diakhiri dengan --
, tetapi itu cukup mudah untuk diperhatikan. Lihat stackoverflow.com/questions/3508252/...
enctype='multipart/form-data
adalah jenis penyandian yang memungkinkan file untuk dikirim melalui POST . Sederhananya, tanpa penyandian file-file ini tidak dapat dikirim melalui POST .
Jika Anda ingin mengizinkan pengguna untuk mengunggah file melalui formulir, Anda harus menggunakan enctype ini .
multipart/form-data
untuk mengirim file non-biner tetapi tidak efisien. Saya percaya menggunakan application/x-www-form-urlencoded
adalah cara yang benar untuk mengirim data non-biner tetapi seseorang dengan pengalaman lebih banyak dengan file non-biner mungkin perlu memperbaiki saya.
multipart/form-data
untuk mengirim file adalah bahwa itu akan bekerja secara otomatis di frontend dan backend. Anda tidak harus melakukan penanganan khusus. Semua file adalah biner walaupun hanya berisi teks. application/x-www-form-urlencoded
adalah cara standar untuk POST suatu formulir tanpa file terlampir. multipart/form-data
adalah cara standar untuk POST formulir dengan file terlampir. (Ada juga banyak pengkodean lainnya, seperti application/json
dan application/json-patch+json
, yang umum untuk komunikasi antara server dan klien.)
multipart/form-data
. Yang tidak bisa Anda lakukan adalah melakukannya dengan menggunakan pengiriman formulir HTML biasa, tanpa JavaScript. Menyetel formulir untuk digunakan multipart/form-data
adalah satu-satunya mekanisme yang disediakan HTML untuk memungkinkan Anda file POST tanpa menggunakan JavaScript. Saya merasa seperti ini tidak cukup jelas dalam jawabannya, dan bahwa pembaca yang naif mungkin berpikir bahwa ketidakmampuan untuk mengirim file tanpa multipart/form-data
adalah keterbatasan HTTP ; bukan itu masalahnya.
Saat mengirimkan formulir, Anda memberi tahu browser Anda untuk mengirim, melalui protokol HTTP, pesan di jaringan, yang terselip di struktur pesan protokol TCP / IP. Halaman HTML memiliki cara untuk mengirim data ke server: dengan menggunakan <form>
s.
Saat formulir dikirimkan, Permintaan HTTP dibuat dan dikirim ke server, pesan akan berisi nama bidang dalam formulir dan nilai yang diisi oleh pengguna. Transmisi ini dapat terjadi dengan POST
atau GET
metode HTTP .
POST
memberitahu browser Anda untuk membangun pesan HTTP dan meletakkan semua konten di tubuh pesan (cara yang sangat berguna dalam melakukan sesuatu, lebih aman dan juga fleksibel).GET
akan mengirimkan data formulir di querystring . Ini memiliki beberapa kendala tentang representasi dan panjang data.Atribut enctype
hanya masuk akal ketika menggunakan POST
metode. Ketika ditentukan, itu memerintahkan browser untuk mengirim formulir dengan menyandikan kontennya dengan cara tertentu. Dari MDN - Formulir enctype :
Ketika nilai atribut metode dikirim, enctype adalah tipe konten MIME yang digunakan untuk mengirimkan formulir ke server.
application/x-www-form-urlencoded
: Ini adalah default. Saat formulir dikirimkan, semua nama dan nilai dikumpulkan dan Pengodean URL dilakukan pada string terakhir.multipart/form-data
: Karakter TIDAK dikodekan. Ini penting ketika formulir memiliki kontrol unggah file. Anda ingin mengirim file biner dan ini memastikan bahwa bitstream tidak diubah.text/plain
: Spaces dapat dikonversi, tetapi tidak ada lagi pengkodean yang dilakukan.Saat mengirimkan formulir, beberapa masalah keamanan dapat muncul sebagaimana dinyatakan dalam RFC 7578 Bagian 7: Data formulir multipart - Pertimbangan keamanan :
Semua perangkat lunak pemrosesan formulir harus memperlakukan data formulir yang disediakan pengguna
dengan sensitivitas, karena seringkali berisi informasi rahasia atau
pengenal pribadi . Ada banyak penggunaan fitur "pengisian otomatis" formulir di browser web; ini dapat digunakan untuk menipu pengguna untuk secara
tidak sadar mengirim informasi rahasia saat menyelesaikan
tugas yang tidak berbahaya. multipart / formulir-data tidak menyediakan fitur apa pun
untuk memeriksa integritas, memastikan kerahasiaan, menghindari
kebingungan pengguna , atau fitur keamanan lainnya; keprihatinan tersebut harus
diatasi dengan aplikasi pengisian formulir dan interpretasi formulir.Aplikasi yang menerima formulir dan memprosesnya harus berhati-hati untuk tidak memasok data kembali ke situs pemrosesan formulir yang meminta yang tidak dimaksudkan untuk dikirim.
Penting ketika menginterpretasikan nama file
bidang header Content- Disposition untuk tidak secara tidak sengaja menimpa file dalam
ruang file penerima.
Ini menjadi perhatian Anda jika Anda seorang pengembang dan server Anda akan memproses formulir yang dikirimkan oleh pengguna yang mungkin akhirnya berisi informasi sensitif.
enctype
yang harus dilakukan. Saya tahu ini benar-benar dari multipart/form-data
RFC, tetapi meskipun demikian itu adalah pertimbangan keamanan yang sewenang-wenang tentang pengiriman formulir yang sepenuhnya ortogonal terhadap apakah data dikirim sebagai application/x-www-form-urlencoded
atau tidak multipart/form-data
.
Setel atribut metode ke POST karena konten file tidak dapat dimasukkan ke dalam parameter URL menggunakan formulir.
Tetapkan nilai enctype ke multipart / form-data karena data akan dipecah menjadi beberapa bagian, satu untuk setiap file plus satu untuk teks dari form tubuh yang mungkin dikirim bersama mereka.
POST
kemungkinan cukup untuk mengirimkan file melalui formulir dan menambahkan multipart/form-data
itu hanya bonus dalam beberapa cara yang tidak jelas. Bukan itu masalahnya. Sebagian besar file benar-benar harus menggunakan multipart/form-data
.
<head>
dan <body>
tidak relevan dan membingungkan.
Biasanya ini adalah ketika Anda memiliki formulir POST yang perlu mengambil unggah file sebagai data ... ini akan memberi tahu server bagaimana ia akan menyandikan data yang ditransfer, dalam kasus seperti itu tidak akan disandikan karena hanya akan mentransfer dan mengunggah file ke server, Sukai misalnya saat mengunggah gambar atau pdf
Atribut enctype menentukan bagaimana bentuk-data harus dikodekan ketika mengirimkannya ke server.
Atribut enctype hanya dapat digunakan jika method = "post".
Tidak ada karakter yang dikodekan. Nilai ini diperlukan saat Anda menggunakan formulir yang memiliki kontrol unggah file
Dari W3Schools
multipart/form-data
. Ini juga sangat tidak jelas; apa arti kalimat "Tidak ada karakter yang disandikan"? -1.