web-dev-qa-db-ja.com

アップロードされたファイルのMIMEタイプはブラウザによってどのように決定されますか?

ユーザーが.Zipファイルをアップロードする必要があるWebアプリがあります。サーバー側では、アップロードされたファイルの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ファイルライブラリをロードしないようにします。

77
Kip

Chrome

Chrome(執筆時点のバージョン38)には、MIMEタイプを特定する3つの方法があり、特定の順序でそうします。以下のスニペットは、ファイル_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=17kPrimaryMappingsおよびkSecondaryMappings)。

例:Microsoft ExcelがインストールされたWindowsシステムからCSVファイルをアップロードする場合、Chromeはこれを_application/vnd.ms-Excel_として報告します。これは_.csv_が最初にハードコードされたリスト、ブラウザはシステムレジストリにフォールバック_HKEY_CLASSES_ROOT\.csv_には_Content Type_という名前の値があり、_application/vnd.ms-Excel_に設定されます。

インターネットエクスプローラ

再び同じ例を使用すると、ブラウザは_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_(上のリストの項目2)にエントリがあるため、ブラウザは_mimeTypes.rdf_を報告します。このエントリを持たない新しいプロファイルでは、ブラウザは_application/vnd.ms-Excel_(リストの項目3)を報告します。

概要

ブラウザのハードコードされたリストはかなり限られています。多くの場合、ブラウザによって送信されるMIMEタイプは、OSによって報告されるものです。そして、これがまさに、質問で述べたように、ブラウザによって報告されたMIMEタイプが信頼できないという理由です。

62
user247702

キップ、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 。これについては、さらに信頼できる情報が必要です。

10
Kumar

これはあなたの質問に対する答えではありませんが、解決しようとしている問題を解決します。 YMMV。

あなたが書いたように、各ブラウザにはそれを決定する方法があるため、MIMEタイプは信頼できません。ただし、ブラウザはファイルの元の名前(拡張子を含む)を送信します。したがって、問題に対処する最善の方法は、MIMEタイプではなくファイルの拡張子を検査することです。

それでもMIMEタイプが必要な場合は、独自のApacheのmime.typesを使用して、サーバー側を決定できます。

5
johndodo

これはおそらくOSであり、ブラウザに依存する可能性がありますが、Windowsでは、特定のファイル拡張子のMIMEタイプはHKCRの下のレジストリを調べることで見つけることができます。

例えば:

HKEY_CLASSES_ROOT.Zip-ContentType

MIMEからファイル拡張子に移動するには、以下のキーを見ることができます

HKEY_CLASSES_ROOT\Mime\Database\Content Type

特定のMIMEタイプのデフォルト拡張子を取得します。

rfc1867-HTMLでのフォームベースのファイルアップロード

メディアタイプがわかっている場合(ファイル拡張子やオペレーティングシステムのタイピング情報から推測される場合)、またはアプリケーション/オクテットストリームとして、各部分に適切なコンテンツタイプのラベルを付ける必要があります。

だから私の理解は、application/octet-streamblanket catch-allタイプをinferredにできない場合の識別子。

0
smwikipedia

私はjohndodoに同意します。ブラウザから送信されるMIMEタイプを信頼できないものにする変数が非常に多くあります。受け取ったサブタイプを除外し、「アプリケーション」などのタイプに焦点を合わせます。アプリがphpベースの場合、explode()関数を使用して簡単にこれを行うことができます。さらに、ファイル拡張子をチェックして、それが.Zipまたは他の探している圧縮であることを確認してください!

0
Seul Shahkee