Как браузер определяет тип mime загруженного файла? - PullRequest
74 голосов
/ 29 июля 2009

У меня есть веб-приложение, в котором пользователю необходимо загрузить ZIP-файл. На стороне сервера я проверяю тип MIME загруженного файла, чтобы убедиться, что это 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-файлов.

Ответы [ 6 ]

59 голосов
/ 10 октября 2014

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, сообщаемый браузером, ненадежен.

10 голосов
/ 05 августа 2011

Кип, я потратил некоторое время на чтение 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. Я все еще хотел бы иметь более авторитетную информацию по этому вопросу.

5 голосов
/ 05 августа 2011

Хотя это не ответ на ваш вопрос, он решает проблему, которую вы пытаетесь решить. YMMV.

Как вы писали, MIME-тип не является надежным, поскольку у каждого браузера есть свой способ его определения. Однако браузеры отправляют оригинальное имя (включая расширение) файла. Поэтому лучший способ справиться с этой проблемой - проверить расширение файла вместо типа MIME.

Если вам все еще нужен тип mime, вы можете использовать свой собственный apache mime.types, чтобы определить его на стороне сервера.

5 голосов
/ 29 июля 2009

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

Например:

HKEY_CLASSES_ROOT.zip - ContentType

Чтобы перейти от MIME к расширению файла, вы можете посмотреть ключи в

HKEY_CLASSES_ROOT \ Mime \ База данных \ Тип содержимого

Чтобы получить расширение по умолчанию для определенного типа MIME.

0 голосов
/ 06 июля 2015

Согласно rfc1867 - загрузка файлов на основе форм в HTML :

Каждая часть должна быть помечена соответствующим типом содержимого, если тип носителя известен (например, выводится из расширения файла или информация о наборе операционной системы) или как application / octet-stream.

Итак, насколько я понимаю, application/octet-stream является своего рода идентификатором blanket catch-all, если тип не может быть выведен .

0 голосов
/ 04 июня 2013

Я согласен с johndodo, существует так много переменных, которые делают MIME-типы, отправляемые из браузеров, ненадежными. Я бы исключил полученные подтипы и сосредоточился только на типе «приложение». если ваше приложение основано на php, вы можете легко сделать это с помощью функции explode (). Кроме того, просто проверьте расширение файла, чтобы убедиться, что это .zip или любое другое сжатие, которое вы ищете!

...