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


87

ユーザーが.zipファイルをアップロードする必要があるWebアプリがあります。サーバー側では、アップロードされたファイルのmimeタイプをチェックして、それがapplication/x-zip-compressedまたはであることを確認していapplication/zipます。

これはFirefoxとIEでうまくいきました。しかし、同僚がそれをテストしたとき、Firefoxでは失敗しました(送信されたmimeタイプは " application/octet-stream"のようなものでした)が、InternetExplorerでは機能しました。私たちのセットアップは同じようです:IE8、FF 3.5.1、すべてのアドオンが無効、Win XP SP3、WinRARがネイティブの.zipファイルハンドラーとしてインストールされています(それが関連するかどうかはわかりません)。

だから私の質問は:ブラウザはどのmimeタイプを送信するかをどのように決定するのですか?

注意:mimeタイプはブラウザによって送信されるため、信頼性が低いことを知っています。私は便宜上それをチェックしています-主に、非zipファイルをzipファイルとして開こうとした場合よりもわかりやすいエラーメッセージを表示し、(おそらく重い)zipファイルライブラリをロードしないようにします。


application / octet-streamはバイナリファイルを指定します。ファイルの拡張子を取得して、zipファイルかどうかを確認できるはずです。明確にするために、これはFFで機能しましたが、同僚では機能しませんでしたか?
ケビンクロウェル

はい、両方のブラウザで機能しました
Kip

input/@formenctypeまたはform/@enctype属性を見てください
tuxSlayer 2013年

回答:


72

クロム

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 = 170kPrimaryMappingsおよびkSecondaryMappings)。

例:Microsoft ExcelがインストールされているWindowsシステムからCSVファイルをアップロードすると、Chromeはこれをとして報告しapplication/vnd.ms-excelます。これは、.csvハードコードされた最初のリストでが指定されていないため、ブラウザがシステムレジストリにフォールバックするためです。HKEY_CLASSES_ROOT\.csvContent 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/csvmimeTypes.rdf(上記のリストの項目2)にエントリがあるため、ブラウザは報告します。このエントリがない新しいプロファイルでは、ブラウザはレポートしますapplication/vnd.ms-excel(リストの項目3)。

概要

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


1
ありがとう!Chromeソースのハードコードされたリストへのリンクはありますか?
キップ

@Kipええ、リンクを追加しました。Firefoxには(公式の)オンラインソースコードブラウザがないようです。FTPサーバーからダウンロードする必要がありました。
user247702 2014年

CSVのms-excelとしてMIMEを使用するのは面倒ですが、ハードコードされたリストにないのはなぜですか。
クリス


1
@VitalyIsaev Chromeコードをざっと見ると、これは2014
わかります。– user2477 0219年

12

キップ、RFC、MSDN、MDNを読んで時間を過ごしました。これが私が理解できたことです。ブラウザは、アップロードするファイルを検出すると、受信したデータの最初のバッファを調べて、テストを実行します。これらのテストは、ファイルが既知のmimeタイプであるかどうかを判別しようとし、既知のmimeタイプである場合は、既知のmimeタイプについてさらにテストし、それに応じてアクションを実行します。IEは、拡張子からファイルタイプを判別するだけでなく、最初にこれを実行しようとしていると思います。このページでは、IEhttp ://msdn.microsoft.com/en-us/library/ms775147%28v=vs.85%29.aspxについて説明しています。Firefoxの場合、私が理解できたのは、ファイルシステムまたはディレクトリエントリからファイル情報を読み取ろうとし、ファイルタイプを判別することでした。FFへのリンクは次のとおりですhttps://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIFile。私はまだこれについてもっと信頼できる情報が欲しいです。


8

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

例えば:

HKEY_CLASSES_ROOT.zip-ContentType

MIMEからファイル拡張子に移行するには、下のキーを確認してください。

HKEY_CLASSES_ROOT \ Mime \ Database \ Content Type

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


ありがとう。残念ながら、私と私の同僚の両方にとって、これは私たちのレジストリでは正しいようです。それが彼のためにIEで機能した理由だと思いますが、FFはどういうわけかそれを異なって取得しています...まあ:(
Kip

5

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

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

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


1
気になりますか?私の経験では、ブラウザは常に正しい元のファイル名(拡張子付き)を送信しますが、MIMEタイプは大きく異なります。そうです、私はそれがはるかに信頼できると言うでしょう。
johndodo 2014年

正しい。エンドユーザーは実際のタイプに関係なく任意の拡張子を付けることができるので、信頼されるべきではないということを意味しました。
djizeus 2014年

それは本当ですが、拡張子とMIMEタイプのどちらを使用するかは問題ではありません。ユーザーが入力したものを、決して信頼してはなりません。しかし、OPはこの問題を認識していると明示的に述べたため、これはこの質問の一部ではありません。ところで、あなたが反対票を削除していただければ幸いです(私はそれがあなたから来たと思います)。
johndodo 2014年

あなたは正しいです、質問にないことに注意を払っていませんでした、私の悪い。投票をキャンセルすることはできますが、その回答を編集する必要があります(システムによって強制されます)...
Djizeus 2014年

ええ、私はjohndodoに同意します。Stijnが上記の回答で説明したように、ChromeとFirefoxは最初に拡張機能をチェックします。彼らは最終的に同じことをしています。
ジェニックス2016年

0

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


0

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

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

だから私の理解は、型が推測できない場合の識別子application/octet-streamのようなものです。blanket catch-all


はい、私はこれをすべて理解しています。問題は、ブラウザがどのように推測するかでした。
キップ2015

それは知っておく価値がありますよね?Ifはapplication/octet-streamキャッチオールである、その後、別のアプローチは、あなたが取得する場合、推測を作ることができている場合は、ブラウザを信頼し、あなた自身のサーバー側のテストを行うことであろうapplication/octet-stream
MikeBeaton 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.