Wie wird der MIME-Typ einer hochgeladenen Datei vom Browser bestimmt?

87

Ich habe eine Web-App, in die der Benutzer eine ZIP-Datei hochladen muss. Auf der Serverseite überprüfe ich den MIME-Typ der hochgeladenen Datei, um sicherzustellen, dass es sich um application/x-zip-compressedoder handelt application/zip.

Dies funktionierte gut für mich unter Firefox und IE. Als ein Mitarbeiter es testete, schlug es für ihn in Firefox fehl (gesendeter MIME-Typ war so etwas wie " application/octet-stream"), funktionierte jedoch in Internet Explorer. Unsere Setups scheinen identisch zu sein: IE8, FF 3.5.1 mit allen deaktivierten Add-Ons, Win XP SP3, WinRAR als nativer ZIP-Dateihandler installiert (nicht sicher, ob dies relevant ist).

Meine Frage lautet also: Wie bestimmt der Browser, welchen MIME-Typ gesendet werden soll?

Bitte beachten Sie: Ich weiß, dass der MIME-Typ vom Browser gesendet wird und daher unzuverlässig ist. Ich überprüfe es nur als Annehmlichkeit - hauptsächlich, um eine freundlichere Fehlermeldung als die zu erhalten, die Sie erhalten, wenn Sie versuchen, eine Nicht-Zip-Datei als Zip-Datei zu öffnen, und um das Laden der (vermutlich schweren) Zip-Dateibibliotheken zu vermeiden.

Pennen
quelle
application / octet-stream bezeichnet eine Binärdatei. Sie sollten in der Lage sein, die Erweiterung der Datei abzurufen, um festzustellen, ob es sich um eine Zip-Datei handelt. Hat das für Sie bei FF funktioniert, aber nicht für Ihren Kollegen?
Kevin Crowell
Ja, es hat bei mir in beiden Browsern funktioniert
Kip
input/@formenctypeform/@enctype
Werfen

Antworten:

71

Chrom

Chrome (Version 38 zum Zeitpunkt des Schreibens) bietet drei Möglichkeiten, um den MIME-Typ zu bestimmen, und zwar in einer bestimmten Reihenfolge. Das folgende Snippet stammt aus der Datei src/net/base/mime_util.cc, Methode 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.

Die fest codierten Listen befinden sich etwas früher in der Datei: https://cs.chromium.org/chromium/src/net/base/mime_util.cc?l=170 ( kPrimaryMappingsund kSecondaryMappings).

Ein Beispiel: Wenn Sie eine CSV-Datei von einem Windows-System mit installiertem Microsoft Excel hochladen, meldet Chrome dies als application/vnd.ms-excel. Dies liegt daran, dass .csvin der ersten fest codierten Liste nichts angegeben ist, sodass der Browser auf die Systemregistrierung zurückgreift. HKEY_CLASSES_ROOT\.csvhat einen Wert namens Content Type, der auf gesetzt ist application/vnd.ms-excel.

Internet Explorer

Wiederum mit demselben Beispiel meldet der Browser application/vnd.ms-excel. Ich denke, es ist vernünftig anzunehmen, dass Internet Explorer (Version 11 zum Zeitpunkt des Schreibens) die Registrierung verwendet. Möglicherweise wird auch eine fest codierte Liste wie Chrome und Firefox verwendet, die jedoch aufgrund ihrer Closed-Source-Natur schwer zu überprüfen ist.

Feuerfuchs

Wie im Chrome-Code angegeben, funktioniert Firefox (Version 32 zum Zeitpunkt des Schreibens) auf ähnliche Weise. Ausschnitt aus Datei uriloader\exthandler\nsExternalHelperAppService.cpp, MethodensExternalHelperAppService::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

Die fest codierten Listen befinden sich früher in der Datei, irgendwo in der Nähe von Zeile 441. Sie suchen nach defaultMimeEntriesund extraMimeEntries.

Bei meinem aktuellen Profil meldet der Browser, text/csvweil in mimeTypes.rdf(Punkt 2 in der obigen Liste) ein Eintrag dafür vorhanden ist . Bei einem neuen Profil, das diesen Eintrag nicht enthält, meldet der Browser application/vnd.ms-excel(Punkt 3 in der Liste).

Zusammenfassung

Die fest codierten Listen in den Browsern sind ziemlich begrenzt. Häufig ist der vom Browser gesendete MIME-Typ der vom Betriebssystem gemeldete. Und genau aus diesem Grund ist der vom Browser gemeldete MIME-Typ, wie in der Frage angegeben, unzuverlässig.

user247702
quelle
1
Vielen Dank! Haben Sie einen Link zur fest codierten Liste in der Chrome-Quelle?
Kip
@Kip ja, ich habe einen Link hinzugefügt. Firefox scheint keinen (offiziellen) Online-Quellcode-Browser zu haben, ich musste ihn von seinem FTP-Server herunterladen.
user247702
Es ist ärgerlich, das MIME als ms-excel für CSV zu haben. Fragen Sie sich, warum es nicht in der fest codierten Liste enthalten ist.
Kris
Es wäre schön zu wissen, ob es seit 2014 einige Aktualisierungen bei der Erkennung von
MIME
1
@VitalyIsaev Ein flüchtiger Blick auf den Chrome-Code zeigt, dass sich dies seit 2014 nicht geändert hat.
user247702
12

Kip, ich habe einige Zeit damit verbracht, RFCs, MSDN und MDN zu lesen. Folgendes konnte ich verstehen. Wenn ein Browser auf eine Datei zum Hochladen stößt, überprüft er den ersten empfangenen Datenpuffer und führt dann einen Test durch. Diese Tests versuchen festzustellen, ob die Datei ein bekannter MIME-Typ ist oder nicht, und wenn ein bekannter MIME-Typ vorliegt, wird sie einfach weiter getestet, für welchen bekannten MIME-Typ, und entsprechende Maßnahmen ergriffen. Ich denke, der IE versucht dies zuerst zu tun, anstatt nur den Dateityp anhand der Erweiterung zu bestimmen. Diese Seite erklärt dies für IE http://msdn.microsoft.com/en-us/library/ms775147%28v=vs.85%29.aspx . Für Firefox konnte ich verstehen, dass es versucht, Dateiinformationen aus dem Dateisystem oder dem Verzeichniseintrag zu lesen und dann den Dateityp bestimmt. Hier ist ein Link für FF https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIFile. Ich hätte gerne noch maßgeblichere Informationen dazu.

Kumar
quelle
8

Dies ist wahrscheinlich vom Betriebssystem und möglicherweise vom Browser abhängig. Unter Windows kann der MIME-Typ für eine bestimmte Dateierweiterung in der Registrierung unter HKCR gefunden werden:

Beispielsweise:

HKEY_CLASSES_ROOT.zip - ContentType

Um von MIME zur Dateierweiterung zu gelangen, können Sie sich die Schlüssel unter ansehen

HKEY_CLASSES_ROOT \ Mime \ Database \ Content Type

Abrufen der Standarderweiterung für einen bestimmten MIME-Typ.

Michael A. McCloskey
quelle
Vielen Dank. Leider scheint dies sowohl für mich als auch für meinen Kollegen in unserer Registrierung korrekt zu sein. Ich denke, deshalb hat es im IE für ihn funktioniert, aber FF bekommt es irgendwie anders ... na ja :(
Kip
5

Dies ist zwar keine Antwort auf Ihre Frage, löst jedoch das Problem, das Sie lösen möchten. YMMV.

Wie Sie geschrieben haben, ist der MIME-Typ nicht zuverlässig, da jeder Browser seine Art hat, ihn zu bestimmen. Browser senden jedoch den ursprünglichen Namen (einschließlich der Erweiterung) der Datei. Der beste Weg, um das Problem zu lösen, besteht darin, die Erweiterung der Datei anstelle des MIME-Typs zu überprüfen.

Wenn Sie den MIME-Typ weiterhin benötigen, können Sie die MIME-Typen Ihres eigenen Apachen verwenden, um ihn serverseitig zu bestimmen.

Johndodo
quelle
1
Möchtest du das näher erläutern? Nach meiner Erfahrung senden Browser immer den richtigen ursprünglichen Dateinamen (mit Erweiterung), während die MIME-Typen stark variieren. Also ja, ich würde sagen, es ist weitaus zuverlässiger.
Johndodo
Richtig. Ich wollte damit sagen, dass der Endbenutzer jede Erweiterung setzen kann, unabhängig vom tatsächlichen Typ, daher sollte ihr nicht vertraut werden.
Djizeus
Das stimmt, aber es spielt keine Rolle, ob Sie eine Erweiterung oder einen MIME-Typ verwenden - Sie sollten niemals den vom Benutzer bereitgestellten Eingaben vertrauen. OP erklärte jedoch ausdrücklich, dass er sich dieses Problems bewusst ist, sodass dies nicht Teil dieser Frage ist. Übrigens würde ich mich freuen, wenn Sie das Downvote entfernen würden (ich nehme an, es kam von Ihnen).
Johndodo
Du hast recht, habe nicht auf das nicht in der Frage geachtet, mein schlechtes. Ich kann meine Abstimmung stornieren, aber Sie müssen die Antwort dafür bearbeiten (vom System erzwungen) ...
Djizeus
Ja, ich stimme Johndodo zu. Wie Stijn in seiner obigen Antwort erklärt hat, überprüfen Chrome und Firefox zuerst die Erweiterung. Am Ende machen sie dasselbe.
Jenix
0

Ich stimme Johndodo zu, es gibt so viele Variablen, die MIME-Typen, die von Browsern gesendet werden, unzuverlässig machen. Ich würde die empfangenen Untertypen ausschließen und mich nur auf den Typ wie "Anwendung" konzentrieren. Wenn Ihre App PHP-basiert ist, können Sie dies einfach mit der Funktion explode () tun. Überprüfen Sie außerdem einfach die Dateierweiterung, um sicherzustellen, dass es sich um .zip oder eine andere gewünschte Komprimierung handelt!

Seul Shahkee
quelle
0

Laut rfc1867 - Formularbasierter Datei-Upload in HTML :

Jeder Teil sollte mit einem geeigneten Inhaltstyp gekennzeichnet werden, wenn der Medientyp bekannt ist (z. B. aus der Dateierweiterung oder den Typisierungsinformationen des Betriebssystems abgeleitet) oder als Anwendung / Oktett-Stream.

Mein Verständnis ist also, application/octet-streamist wie eine blanket catch-allKennung, wenn der Typ nicht abgeleitet werden kann .

smwikipedia
quelle
Ja, ich verstehe das alles. Die Frage war, wie der Browser darauf schließen kann.
Kip
Das ist aber wissenswert, oder? Wenn dies application/octet-streamder Haken ist, besteht ein anderer Ansatz darin, dem Browser zu vertrauen, wenn er eine Vermutung anstellen konnte, und gegebenenfalls Ihre eigenen serverseitigen Tests durchzuführen application/octet-stream.
MikeBeaton