Ketika saya mengirimkan formulir sederhana seperti ini dengan file terlampir:
<form enctype="multipart/form-data" action="http://localhost:3000/upload?upload_progress_id=12344" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="100000" />
Choose a file to upload: <input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
Bagaimana cara mengirim file secara internal? Apakah file dikirim sebagai bagian dari badan HTTP sebagai data? Di tajuk permintaan ini, saya tidak melihat apa pun yang terkait dengan nama file.
Saya hanya ingin mengetahui cara kerja internal HTTP saat mengirim file.
http
file-upload
0xSina
sumber
sumber
MAX_FILE_SIZE
di PHP - apa gunanya" di stackoverflow.com/q/1381364/632951Jawaban:
Mari kita lihat apa yang terjadi ketika Anda memilih file dan mengirimkan formulir Anda (saya telah memotong header untuk singkatnya):
CATATAN: setiap string batas harus diawali dengan tambahan
--
, sama seperti pada akhir string batas terakhir. Contoh di atas sudah termasuk ini, tetapi bisa mudah dilewatkan. Lihat komentar olehAndreas di bawah ini.Alih-alih URL yang menyandikan parameter formulir, parameter formulir (termasuk data file) dikirim sebagai bagian dalam dokumen multi bagian di badan permintaan.
Dalam contoh di atas, Anda dapat melihat input
MAX_FILE_SIZE
dengan nilai yang ditetapkan dalam formulir, serta bagian yang berisi data file. Nama file adalah bagian dariContent-Disposition
tajuk.Detail lengkapnya ada di sini .
sumber
Format ini disebut
multipart/form-data
, seperti yang ditanyakan pada: Apa arti enctype = 'multipart / form-data'?Saya akan:
Referensi HTML5
Ada tiga kemungkinan untuk
enctype
:x-www-urlencoded
multipart/form-data
(spec menunjuk ke RFC2388 )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.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:
nc -l
atau server ECHO: server uji HTTP yang menerima permintaan GET / POSTSimpan formulir ke
.html
file minimal :Kami menetapkan nilai teks default menjadi
aωb
, yang berartiaωb
karenaω
isU+03C9
, yang merupakan byte61 CF 89 62
dalam UTF-8.Buat file untuk diunggah:
Jalankan server gema kecil kami:
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.multipart / formulir-data
Firefox mengirim:
Untuk file biner dan bidang teks, byte
61 CF 89 62
(aωb
dalam UTF-8) dikirim secara harfiah. Anda dapat memverifikasi itu dengannc -l localhost 8000 | hd
, yang mengatakan bahwa byte:dikirim (
61
== 'a' dan62
== 'b').Karena itu jelas bahwa:
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
setel jenis konten menjadimultipart/form-data
dan mengatakan bahwa bidang dipisahkan olehboundary
string yang diberikan .Tetapi perhatikan bahwa:
memiliki dua ayah kurang
--
dari penghalang yang sebenarnyaIni 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:setiap bidang mendapatkan beberapa subjudul sebelum datanya
Content-Disposition: form-data;
:, bidangname
,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- afterencesContent-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
enctype
keapplication/x-www-form-urlencoded
, muat ulang peramban, dan kirim kembali.Firefox mengirim:
Jelas data file tidak dikirim, hanya nama dasarnya. Jadi ini tidak dapat digunakan untuk file.
Sedangkan untuk bidang teks, kita melihat bahwa karakter yang biasa dicetak suka
a
danb
dikirim dalam satu byte, sementara yang tidak dapat dicetak suka0xCF
dan masing-masing0x89
mengambil 3 byte :%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.Karena itu, bahkan jika kita 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.
sumber
Content-Disposition
danContent-Type
atribut tetapi bagaimana menangani 'konten'?Kirim file sebagai konten biner (unggah tanpa formulir atau FormData)
Dalam jawaban / contoh yang diberikan, file tersebut (kemungkinan besar) diunggah dengan formulir HTML atau menggunakan API FormData . File hanya merupakan bagian dari data yang dikirim dalam permintaan, karenanya
multipart/form-data
Content-Type
header.Jika Anda ingin mengirim file sebagai satu-satunya konten maka Anda dapat langsung menambahkannya sebagai badan permintaan dan Anda mengatur
Content-Type
header ke tipe MIME dari file yang Anda kirim. Nama file dapat ditambahkan diContent-Disposition
header. Anda dapat mengunggah seperti ini:Jika Anda tidak (ingin) menggunakan formulir dan Anda hanya tertarik untuk mengunggah satu file saja, ini adalah cara termudah untuk memasukkan file Anda dalam permintaan.
sumber
Content-Type
dari header.Saya punya contoh Kode Java ini:
dan saya punya file test.html ini:
dan akhirnya file yang akan saya gunakan untuk tujuan pengujian, bernama a.dat memiliki konten berikut:
jika Anda menafsirkan byte di atas sebagai karakter ASCII atau UTF-8, mereka akan benar-benar mewakili:
Jadi mari kita jalankan Kode Java kita, buka test.html di browser favorit kita, unggah
a.dat
dan kirim formulir dan lihat apa yang server kami terima:Ya saya tidak terkejut melihat karakternya 9ie karena kami memberitahu Java untuk mencetaknya dengan memperlakukan mereka sebagai karakter UTF-8. Anda juga dapat memilih untuk membacanya sebagai byte mentah ..
sebenarnya adalah HTTP Header terakhir di sini. Setelah itu muncul HTTP Body, tempat meta dan konten file yang kita unggah sebenarnya bisa dilihat.
sumber
http://www.tutorialspoint.com/http/http_messages.htm
sumber