Bagaimana jenis mime dari file yang diunggah ditentukan oleh browser?

87

Saya memiliki aplikasi web tempat pengguna perlu mengunggah file .zip. Di sisi server, saya memeriksa jenis mime dari file yang diunggah, untuk memastikannya adalah application/x-zip-compressedatau application/zip.

Ini berfungsi dengan baik untuk saya di Firefox dan IE. Namun, saat rekan kerja mengujinya, ia gagal di Firefox (jenis pantomim yang dikirim adalah seperti " application/octet-stream") tetapi bekerja di Internet Explorer. Setup kami tampaknya identik: IE8, FF 3.5.1 dengan semua add-on dinonaktifkan, Win XP SP3, WinRAR diinstal sebagai penangan file .zip asli (tidak yakin apakah itu relevan).

Jadi pertanyaan saya adalah: Bagaimana browser menentukan jenis mime yang akan dikirim?

Harap diperhatikan: Saya tahu bahwa jenis pantomim dikirim oleh browser dan, oleh karena itu, tidak dapat diandalkan. Saya hanya memeriksanya sebagai kemudahan - terutama untuk memberikan pesan kesalahan yang lebih bersahabat daripada yang Anda dapatkan dengan mencoba membuka file non-zip sebagai file zip, dan untuk menghindari memuat pustaka file zip (mungkin berat).

Tidur
sumber
application / octet-stream menunjukkan file biner. Anda seharusnya bisa mendapatkan ekstensi file untuk melihat apakah itu file zip. Hanya untuk memperjelas, apakah ini berhasil untuk Anda di FF, tetapi tidak untuk rekan kerja Anda?
Kevin Crowell
ya, ini berhasil untuk saya di kedua browser
Kip
lihat input/@formenctypeatau form/@enctypeatribut
tuxSlayer

Jawaban:

72

Chrome

Chrome (versi 38 pada saat penulisan) memiliki 3 cara untuk menentukan jenis MIME dan melakukannya dalam urutan tertentu. Cuplikan di bawah ini berasal dari file src/net/base/mime_util.cc, metode MimeUtil::GetMimeTypeFromExtensionHelper.

// We implement the same algorithm as Mozilla for mapping a file extension to
// a mime type.  That is, we first check a hard-coded list (that cannot be
// overridden), and then if not found there, we defer to the system registry.
// Finally, we scan a secondary hard-coded list to catch types that we can
// deduce but that we also want to allow the OS to override.

Daftar hard-coded muncul sedikit lebih awal di file: https://cs.chromium.org/chromium/src/net/base/mime_util.cc?l=170 ( kPrimaryMappingsdan kSecondaryMappings).

Contoh: saat mengunggah file CSV dari sistem Windows dengan Microsoft Excel terpasang, Chrome akan melaporkannya sebagai application/vnd.ms-excel. Ini karena .csvtidak ditentukan dalam daftar kode keras pertama, sehingga browser kembali ke registri sistem. HKEY_CLASSES_ROOT\.csvmemiliki nilai bernama Content Typeyang disetel ke application/vnd.ms-excel.

Internet Explorer

Sekali lagi menggunakan contoh yang sama, browser akan melaporkan application/vnd.ms-excel. Saya pikir masuk akal untuk menganggap Internet Explorer (versi 11 saat penulisan) menggunakan registri. Mungkin itu juga menggunakan daftar hard-coded seperti Chrome dan Firefox, tetapi sifatnya yang closed source membuatnya sulit untuk diverifikasi.

Firefox

Seperti yang ditunjukkan dalam kode Chrome, Firefox (versi 32 pada saat penulisan) bekerja dengan cara yang sama. Cuplikan dari file uriloader\exthandler\nsExternalHelperAppService.cpp, metodensExternalHelperAppService::GetTypeFromExtension

// OK. We want to try the following sources of mimetype information, in this order:
// 1. defaultMimeEntries array
// 2. User-set preferences (managed by the handler service)
// 3. OS-provided information
// 4. our "extras" array
// 5. Information from plugins
// 6. The "ext-to-type-mapping" category

Daftar hard-coded muncul lebih awal dalam file, dekat baris 441. Anda sedang mencari defaultMimeEntriesdan extraMimeEntries.

Dengan profil saya saat ini, browser akan melaporkan text/csvkarena ada entri untuk profil itu di mimeTypes.rdf(item 2 di daftar di atas). Dengan profil baru, yang tidak memiliki entri ini, browser akan melaporkan application/vnd.ms-excel(item 3 dalam daftar).

Ringkasan

Daftar hard-coded di browser sangat terbatas. Seringkali, jenis MIME yang dikirim oleh browser adalah yang dilaporkan oleh OS. Dan inilah tepatnya mengapa, seperti yang dinyatakan dalam pertanyaan, tipe MIME yang dilaporkan oleh browser tidak dapat diandalkan.

pengguna247702
sumber
1
Terima kasih! apakah Anda memiliki tautan ke daftar hard-coded di sumber chrome?
Kip
@Kip ya, saya telah menambahkan tautan. Firefox tampaknya tidak memiliki peramban kode sumber daring (resmi), saya harus mengunduhnya dari server FTP mereka.
pengguna247702
Memiliki MIME sebagai ms-excel untuk CSV memang menjengkelkan, bertanya-tanya mengapa itu tidak ada dalam daftar hardcode.
Kris
Alangkah baiknya mengetahui jika ada beberapa pembaruan dalam deteksi tipe pantomim sejak 2014.
Vitaly Isaev
1
@VitalyIsaev sekilas melihat kode Chrome menunjukkan bahwa ini tidak berubah sejak 2014.
user247702
12

Kip, saya menghabiskan beberapa waktu membaca RFC, MSDN dan MDN. Inilah yang bisa saya pahami. Saat browser menemukan file untuk diunggah, browser melihat buffer pertama dari data yang diterimanya dan kemudian menjalankan pengujian padanya. Tes ini mencoba untuk menentukan apakah file tersebut adalah jenis pantomim yang dikenal atau bukan, dan jika jenis pantomim diketahui, ia hanya akan mengujinya lebih lanjut untuk jenis pantomim yang diketahui dan mengambil tindakan yang sesuai. Saya pikir IE mencoba melakukan ini terlebih dahulu daripada hanya menentukan jenis file dari ekstensi. Halaman ini menjelaskan hal ini untuk IE http://msdn.microsoft.com/en-us/library/ms775147%28v=vs.85%29.aspx . Untuk firefox, yang dapat saya pahami adalah mencoba membaca info file dari sistem file atau entri direktori dan kemudian menentukan jenis file. Ini adalah tautan untuk FF https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIFile. Saya masih ingin mendapatkan info lebih resmi tentang ini.

Kumar
sumber
8

Ini mungkin OS dan mungkin bergantung pada browser, tetapi pada Windows, tipe MIME untuk ekstensi file tertentu dapat ditemukan dengan melihat di registri di bawah HKCR:

Sebagai contoh:

HKEY_CLASSES_ROOT.zip - JenisKonten

Untuk beralih dari MIME ke ekstensi file, Anda dapat melihat tombol di bawah

HKEY_CLASSES_ROOT \ Mime \ Database \ Jenis Konten

Untuk mendapatkan ekstensi default untuk jenis MIME tertentu.

Michael A. McCloskey
sumber
Terima kasih. sayangnya, untuk saya dan rekan kerja saya ini tampaknya benar di registri kami. saya rasa itulah mengapa itu berhasil di IE untuknya, tetapi FF entah bagaimana membuatnya berbeda ... oh well :(
Kip
5

Meskipun ini bukan jawaban untuk pertanyaan Anda, ini memecahkan masalah yang Anda coba selesaikan. YMMV.

Seperti yang Anda tulis, jenis pantomim tidak dapat diandalkan karena setiap browser memiliki cara untuk menentukannya. Namun, browser mengirimkan nama asli (termasuk ekstensi) dari file tersebut. Jadi cara terbaik untuk mengatasi masalah ini adalah dengan memeriksa ekstensi file, bukan tipe MIME.

Jika Anda masih membutuhkan jenis mime, Anda dapat menggunakan mime.types apache Anda sendiri untuk menentukannya di sisi server.

johndodo
sumber
1
Mau menjelaskan lebih lanjut? Dalam pengalaman saya, browser selalu mengirimkan nama file asli yang benar (dengan ekstensi) sementara jenis MIME sangat bervariasi. Jadi ya, menurut saya ini jauh lebih dapat diandalkan.
johndodo
Benar. Saya bermaksud mengatakan bahwa pengguna akhir dapat menempatkan ekstensi apa pun, apa pun jenis aslinya, jadi itu tidak boleh dipercaya.
Djizeus
Itu benar, tetapi tidak masalah jika Anda menggunakan ekstensi atau tipe MIME - Anda tidak boleh mempercayai input yang diberikan pengguna. Tetapi OP menyatakan secara eksplisit bahwa dia menyadari masalah ini, jadi ini bukan bagian dari pertanyaan ini. Btw, saya akan sangat menghargai jika Anda menghapus downvote (saya anggap itu berasal dari Anda).
johndodo
Anda benar, tidak memperhatikan yang tidak di pertanyaan, saya buruk. Saya dapat membatalkan suara saya tetapi Anda harus mengedit jawaban untuk itu (diberlakukan oleh sistem) ...
Djizeus
Ya, saya setuju dengan johndodo. Seperti yang dijelaskan Stijn dalam jawabannya di atas, Chrome dan Firefox memeriksa ekstensinya terlebih dahulu. Mereka melakukan hal yang sama pada akhirnya.
Jenix
0

Saya setuju dengan johndodo, ada banyak sekali variabel yang membuat jenis mime yang dikirim dari browser tidak bisa diandalkan. Saya akan mengecualikan subtipe yang diterima dan hanya fokus pada tipe seperti 'aplikasi'. jika aplikasi Anda berbasis php, Anda dapat dengan mudah melakukan ini dengan menggunakan fungsi explode (). selain itu, cukup periksa ekstensi file untuk memastikannya .zip atau kompresi lain yang Anda cari!

Seul Shahkee
sumber
0

Menurut rfc1867 - Unggahan file berbasis formulir dalam HTML :

Setiap bagian harus diberi label dengan jenis konten yang sesuai jika jenis medianya diketahui (misalnya, disimpulkan dari ekstensi file atau informasi pengetikan sistem operasi) atau sebagai aliran aplikasi / oktet.

Jadi pemahaman saya adalah, application/octet-streamini seperti blanket catch-allpengenal jika jenisnya tidak dapat disimpulkan .

smwikipedia
sumber
ya, saya mengerti semua ini. pertanyaannya adalah bagaimana browser menyimpulkan.
Kip
Itu perlu diketahui, bukan? Jika application/octet-streambersifat catch-all, maka pendekatan lain adalah mempercayai browser jika browser tersebut dapat menebak, dan melakukan pengujian sisi server Anda sendiri jika mendapatkannya application/octet-stream.
MikeBeaton