Apa arti enctype = 'multipart / form-data'?

Jawaban:

1570

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:

  • Jangan pernah gunakan text/plain.

Saat Anda menulis kode sisi klien:

  • gunakan multipart/form-datasaat formulir Anda menyertakan <input type="file">elemen apa pun
  • jika tidak, Anda dapat menggunakan multipart/form-dataatau application/x-www-form-urlencodedtetapi application/x-www-form-urlencodedakan lebih efisien

Saat Anda menulis kode sisi server:

  • Gunakan pustaka penanganan formulir prewritten

Sebagian besar (seperti Perl CGI->paramatau yang diekspos oleh $_POSTsuperglobal 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-datasecara signifikan lebih rumit tetapi memungkinkan seluruh file untuk dimasukkan dalam data. Contoh hasilnya dapat ditemukan dalam spesifikasi HTML 4 .

text/plaindiperkenalkan 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).

Quentin
sumber
5
@ Quentin Maaf, apa masalah yang mungkin terjadi jika kita menggunakan multipart untuk semua formulir? dengan dan memutihkan file.
Webinan
12
Tidak masuk akal untuk mendapatkan formulir, dan itu membuat ukuran file permintaan lebih besar.
Quentin
@ Quentin apakah data formulir multi bagian dikirim sebagai aliran secara default?
Growler
Apakah enc dalam enctype berdiri untuk sesuatu?
Philip Rego
1
"Formulir HTML menyediakan tiga metode ENC oding"
Quentin
449

kapan kita harus menggunakannya

Jawaban Quentin benar: gunakan multipart/form-datajika formulir berisi unggahan file, dan application/x-www-form-urlencodedsebaliknya, yang merupakan default jika Anda hilangkan enctype.

Saya akan:

  • tambahkan beberapa referensi HTML5 lainnya
  • jelaskan mengapa dia benar dengan formulir serahkan contoh

Referensi HTML5

Ada tiga kemungkinan untuk enctype:

Cara menghasilkan contoh

Setelah Anda melihat contoh masing-masing metode, menjadi jelas bagaimana cara kerjanya, dan kapan Anda harus menggunakannya.

Anda dapat menghasilkan contoh menggunakan:

Simpan formulir ke .htmlfile 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&#x03C9;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&#x03C9;b, yang berarti aωbkarena ωmerupakan U+03C9, yang merupakan byte 61 CF 89 62dalam 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, ncBSD 1.105, Firefox 40.

multipart / formulir-data

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ωbdalam 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=---------------------------735323031399963166993862150mengatur jenis konten multipart/form-datadan mengatakan bahwa bidang dipisahkan oleh boundarystring 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?

application / x-www-form-urlencoded

Sekarang ubah enctypeke 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 adan bdikirim dalam satu byte, sedangkan yang non-printable seperti 0xCFdan 0x89mengambil 3 byte masing-masing: %CF%89!

Perbandingan

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.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
3
@ Khanna111 %CFadalah 3 byte panjang: %, Cdan F:-) Kisah sehingga dapat dibaca manusia.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
6
Pada OS X, nctidak akan menerima baik -ldan -pargumen secara bersamaan. Tapi ini bekerja untuk saya: while true; do printf '' | nc -l 8000; done.
PhilipS
4
Poin kecil tapi penting yang tidak disebutkan adalah bahwa batas yang ditentukan dalam Content-Typememiliki 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/...
Bernard
1
Sejauh yang saya tahu, titik menempatkan SETIAP DASHES SEMUA dalam batas adalah untuk membuat mustahil untuk memeriksa sintaks permintaan dengan mata. Tolong jangan menggunakannya di token batas Anda.
Dewi Morgan
1
@DewiMorgan Anda sepenuhnya benar. Saya mengedit posting dan menghapus tanda hubung dari string batas.
Maks
91

enctype='multipart/form-dataadalah 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 .

Matt Asbury
sumber
Jadi .. jika file tersebut bukan file biner maka dapatkah kita bekerja tanpa ini?
Yugal Jindle
Dari apa yang saya mengerti, Anda dapat menggunakan multipart/form-datauntuk mengirim file non-biner tetapi tidak efisien. Saya percaya menggunakan application/x-www-form-urlencodedadalah cara yang benar untuk mengirim data non-biner tetapi seseorang dengan pengalaman lebih banyak dengan file non-biner mungkin perlu memperbaiki saya.
Matt Asbury
11
Keuntungan utama menggunakan multipart/form-datauntuk 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-urlencodedadalah cara standar untuk POST suatu formulir tanpa file terlampir. multipart/form-dataadalah cara standar untuk POST formulir dengan file terlampir. (Ada juga banyak pengkodean lainnya, seperti application/jsondan application/json-patch+json, yang umum untuk komunikasi antara server dan klien.)
Daniel Luna
6
Nilainya menunjukkan Anda dapat base64 menyandikan gambar Anda dan mengirimkannya sebagai data string biasa.
James
3
Selanjutnya ke komentar @ Prospero di atas: Anda benar-benar dapat mengirim file melalui POST tanpa menggunakan multipart/form-data. Yang tidak bisa Anda lakukan adalah melakukannya dengan menggunakan pengiriman formulir HTML biasa, tanpa JavaScript. Menyetel formulir untuk digunakan multipart/form-dataadalah 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-dataadalah keterbatasan HTTP ; bukan itu masalahnya.
Mark Amery
81

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 POSTatau 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).
  • GETakan mengirimkan data formulir di querystring . Ini memiliki beberapa kendala tentang representasi dan panjang data.

Menyatakan cara mengirim formulir Anda ke server

Atribut enctypehanya masuk akal ketika menggunakan POSTmetode. 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.

Keamanan

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.

Andry
sumber
1
Hal-hal tentang keamanan setelah pengeditan terbaru semuanya tidak relevan dengan pertanyaan tentang apa enctypeyang harus dilakukan. Saya tahu ini benar-benar dari multipart/form-dataRFC, 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-urlencodedatau tidak multipart/form-data.
Mark Amery
38

enctype='multipart/form-data'berarti tidak ada karakter yang akan dikodekan. itulah sebabnya jenis ini digunakan saat mengunggah file ke server.
Jadi multipart/form-datadigunakan ketika formulir membutuhkan data biner, seperti konten file, untuk diunggah

GP Singh
sumber
8

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.

berpasir
sumber
Ini menyiratkan bahwa POSTkemungkinan cukup untuk mengirimkan file melalui formulir dan menambahkan multipart/form-dataitu hanya bonus dalam beberapa cara yang tidak jelas. Bukan itu masalahnya. Sebagian besar file benar-benar harus menggunakan multipart/form-data.
underscore_d
1
  • Atribut enctype ( ENC ode TYPE ) menentukan bagaimana bentuk-data harus dikodekan ketika mengirimkannya ke server.
  • multipart / form-data adalah salah satu nilai atribut enctype, yang digunakan dalam elemen form yang memiliki unggahan file. multi-bagian berarti data formulir dibagi menjadi beberapa bagian dan dikirim ke server.
Premraj
sumber
5
Saya percaya enctype tidak mewakili tipe enkripsi. Tidak ada enkripsi yang terlibat pada level ini. Dugaan saya adalah tipe penyandian atau tipe terlampir. Tapi yang pasti bukan tipe enkripsi.
Yeo
1
Poin terakhir Anda di sini tentang <head>dan <body>tidak relevan dan membingungkan.
Mark Amery
0

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

Eric
sumber
-3

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

Rishad
sumber
2
Kutipan ini bahkan tidak menyebutkan multipart/form-data. Ini juga sangat tidak jelas; apa arti kalimat "Tidak ada karakter yang disandikan"? -1.
Mark Amery