Як браузер визначає тип mime завантаженого файлу?


87

У мене є веб-програма, куди користувачеві потрібно завантажити файл .zip. На стороні сервера, я перевірка міма типу завантаженого файлу, щоб переконатися , що він application/x-zip-compressedабо application/zip.

Це добре працювало для мене у Firefox та IE. Однак коли його співробітник перевірив, це не вдалося йому у Firefox (тип mime-файлу був приблизно на зразок " application/octet-stream"), але працював в Internet Explorer. Наші установки схожі на однакові: IE8, FF 3.5.1 з вимкненими всіма доповненнями, Win XP SP3, WinRAR, встановлений як власний обробник файлів .zip (не впевнений, що це доречно).

Тож моє запитання: Як браузер визначає, який тип mime надсилати?

Зверніть увагу: я знаю, що тип mime надсилається браузером і, отже, ненадійний. Я просто перевіряю це як зручність - головним чином, щоб надати більш дружнє повідомлення про помилку, ніж те, що ви отримуєте, намагаючись відкрити файл, що не є zip, як zip-файл, і щоб уникнути завантаження (імовірно важких) бібліотек zip-файлів.


application / octet-stream позначає двійковий файл. Ви зможете отримати розширення файлу, щоб побачити, чи це файл zip. Тільки для уточнення, чи працювало це у вас на FF, але не у вашого колеги?
Kevin Crowell

так, це працювало для мене в обох браузерах
Kip

подивіться на input/@formenctypeабо form/@enctypeатрибути
tuxSlayer

Відповіді:


72

Chrome

Chrome (версія 38 на момент написання) має 3 способи визначити тип MIME і робить це в певному порядку. Фрагмент нижче - з файлу src/net/base/mime_util.cc, методу 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.

Закодовані списки з’являються дещо раніше у файлі: https://cs.chromium.org/chromium/src/net/base/mime_util.cc?l=170 ( kPrimaryMappingsта kSecondaryMappings).

Приклад: під час завантаження файлу CSV із системи Windows із встановленим Microsoft Excel Chrome повідомляє про це як application/vnd.ms-excel. Це пов’язано з тим, що .csvце не вказано в першому кодованому списку, тому браузер повертається до системного реєстру. HKEY_CLASSES_ROOT\.csvмає значення з іменем Content Type, для якого встановлено application/vnd.ms-excel.

Internet Explorer

Знову ж, використовуючи той самий приклад, браузер подасть звіт application/vnd.ms-excel. Думаю, розумно припустити, що Internet Explorer (версія 11 на момент написання) використовує реєстр. Можливо, він також використовує жорстко закодований список, такий як Chrome і Firefox, але його закрите джерело ускладнює перевірку.

Firefox

Як зазначено в коді Chrome, Firefox (версія 32 на момент написання) працює подібним чином. Фрагмент із файлу uriloader\exthandler\nsExternalHelperAppService.cpp, методnsExternalHelperAppService::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

Точно закодовані списки з’являються раніше у файлі, десь біля рядка 441. Ви шукаєте defaultMimeEntriesта extraMimeEntries.

З моїм поточним профілем браузер звітуватиме, text/csvоскільки в ньому є запис mimeTypes.rdf(пункт 2 у списку вище). Зі свіжим профілем, у якому немає цього запису, браузер подасть звіт application/vnd.ms-excel(пункт 3 у списку).

Резюме

Складно закодовані списки в браузерах досить обмежені. Часто тип MIME, що надсилається браузером, буде типом, про який повідомляє ОС. І саме тому, як зазначено у питанні, тип MIME, про який повідомляє браузер, є ненадійним.


1
Дякую! у вас є посилання на жорстко закодований список у джерелі хрому?
Кіп

@Kip так, я додав посилання. Схоже, у Firefox немає (офіційного) веб-переглядача вихідних кодів, мені довелося завантажити його з їх FTP-сервера.
user247702

Маючи MIME як ms-excel для CSV, це дратує, дивуйтеся, чому його немає в жорстко закодованому списку.
Кріс

Було б непогано знати, чи були якісь оновлення щодо виявлення типу mime з 2014 року
Віталій Ісаєв

1
@VitalyIsaev побіжний погляд на код Chrome показує, що це не змінилося з 2014 року
user247702

12

Кіп, я деякий час читав RFC, MSDN та MDN. Ось те, що я міг зрозуміти. Коли браузер стикається з файлом для завантаження, він переглядає перший отриманий буфер даних, а потім запускає на ньому тест. Ці тести намагаються визначити, чи є файл відомим типом mime чи ні, і якщо відомий тип mime, він просто буде додатково тестувати його щодо відомого типу mime і вживати відповідних заходів. Я думаю, IE намагається зробити це спочатку, а не просто визначати тип файлу з розширення. Ця сторінка пояснює це для IE http://msdn.microsoft.com/en-us/library/ms775147%28v=vs.85%29.aspx . Щодо Firefox, я зрозумів, що він намагається зчитувати інформацію про файл із файлової системи або запису в каталозі, а потім визначає тип файлу. Ось посилання на FF https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIFile. Я все-таки хотів би мати більше авторитетної інформації щодо цього.


8

Це, ймовірно, залежить від ОС і, можливо, від браузера, але в Windows тип MIME для даного розширення файлу можна знайти, переглянувши в реєстрі під HKCR:

Наприклад:

HKEY_CLASSES_ROOT.zip - Тип вмісту

Щоб перейти від MIME до розширення файлу, ви можете подивитися клавіші під

HKEY_CLASSES_ROOT \ Mime \ Database \ Content Type

Щоб отримати розширення за замовчуванням для певного типу MIME.


Дякую. на жаль, і для мене, і для мого колеги це здається правильним у нашому реєстрі. я думаю, саме тому він працював в IE для нього, але FF отримує це якось інакше ... ну добре :(
Kip

5

Хоча це не відповідь на ваше запитання, воно вирішує проблему, яку ви намагаєтесь вирішити. YMMV.

Як ви писали, тип mime не є надійним, оскільки кожен браузер має свій спосіб його визначення. Однак браузери надсилають оригінальне ім'я (включаючи розширення) файлу. Тож найкращий спосіб вирішити проблему - перевірити розширення файлу замість типу MIME.

Якщо вам все ще потрібен тип mime, ви можете використовувати mime.types вашого власного apache для визначення його на стороні сервера.


1
Хочете докладно розробити? З мого досвіду, браузери завжди надсилають правильне оригінальне ім’я файлу (із розширенням), тоді як типи MIME сильно відрізняються. Так що так, я б сказав, що це набагато надійніше.
johndodo

Правильно. Я хотів сказати, що кінцевий користувач може поставити будь-яке розширення, незалежно від фактичного типу, тому йому не слід довіряти.
Джизеус

Це правда, але неважливо, використовуєте ви розширення або тип MIME - ніколи не слід довіряти введеному користувачем вводу. Але ОП прямо заявив, що він знає про цю проблему, тому це не є частиною цього питання. До речі, я був би вдячний, якщо б ви зняли голос проти (я припускаю, що він надійшов від вас).
johndodo

Ви маєте рацію, не звертали уваги на не в питанні, мій поганий. Я можу скасувати свій голос, але вам доведеться відредагувати відповідь на це (накладено системою) ...
Джизей

Так, я погоджуюсь з johndodo. Як пояснив Stijn у своїй відповіді вище, Chrome та Firefox спочатку перевіряють розширення. Зрештою вони роблять те саме.
Jenix

0

Я згоден з johndodo, існує так багато змінних, які роблять типи mime, які надсилаються з браузерів, ненадійними. Я б виключив отримані підтипи і просто зосередився на типі типу "додаток". якщо ваш додаток заснований на php, ви можете легко зробити це за допомогою функції explode (). крім того, просто перевірте розширення файлу, щоб переконатися, що це .zip або будь-яке інше стиснення, яке ви шукаєте!


0

Відповідно до rfc1867 - Завантаження файлів на основі форми в HTML :

Кожна частина повинна бути позначена відповідним типом вмісту, якщо тип носія відомий (наприклад, випливає з розширення файлу або інформації про введення операційної системи) або як додаток / октет-потік.

Таким чином , моє розуміння, application/octet-streamце ніби як blanket catch-allідентифікатор , якщо тип не може бути виведений .


так, я все це розумію. питання полягало в тому, як браузер робить висновок.
Кіп

Це варто знати, правда? Якщо application/octet-streamце загальне, тоді іншим підходом буде довіра браузеру, якщо він зміг здогадатися, та проведення власних тестів на стороні сервера, якщо отримаєте application/octet-stream.
MikeBeaton
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.