it-swarm.com.de

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

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-compressed Oder application/Zip Handelt.

Dies hat bei Firefox und IE einwandfrei funktioniert. Als ein Mitarbeiter es testete, schlug es für ihn in Firefox fehl (der gesendete MIME-Typ war etwa "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 systemeigener ZIP-Datei-Handler installiert (nicht sicher, ob dies relevant ist).

Meine Frage lautet also: Wie bestimmt der Browser, welcher 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 aus Bequemlichkeitsgründen - 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.

77
Kip

Chrome

Chrome (Version 38 zum Zeitpunkt des Schreibens) hat drei Möglichkeiten, 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 hartcodierten Listen kommen etwas früher in der Datei: https://cs.chromium.org/chromium/src/net/base/mime_util.cc?l=17 (kPrimaryMappings und kSecondaryMappings).

Ein Beispiel: Wenn Sie eine CSV-Datei von einem Windows-System mit installiertem Microsoft Excel hochladen, gibt Chrome als application/vnd.ms-Excel Aus. Dies liegt daran, dass .csv Nicht angegeben ist In der ersten hartcodierten Liste greift der Browser auf die Systemregistrierung zurück. HKEY_CLASSES_ROOT\.csv hat einen Wert mit dem Namen Content Type, der auf application/vnd.ms-Excel festgelegt ist.

Internet Explorer

Unter Verwendung desselben Beispiels meldet der Browser application/vnd.ms-Excel. Ich halte es für vernünftig anzunehmen, dass der Internet Explorer (Version 11 zum Zeitpunkt des Schreibens) die Registrierung verwendet. Möglicherweise wird auch eine fest codierte Liste wie Chrome und Firefox verwendet, aber aufgrund der geschlossenen Quellennatur ist die Überprüfung schwierig.

Feuerfuchs

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

Die hartcodierten Listen kommen früher in der Datei, irgendwo in der Nähe von Zeile 441. Sie suchen nach defaultMimeEntries und extraMimeEntries.

Bei meinem aktuellen Profil meldet der Browser text/csv, Da in mimeTypes.rdf (Punkt 2 in der obigen Liste) ein Eintrag dafür vorhanden ist. Bei einem neuen Profil ohne diesen Eintrag meldet der Browser application/vnd.ms-Excel (Punkt 3 in der Liste).

Zusammenfassung

Die hartcodierten Listen in den Browsern sind ziemlich begrenzt. Häufig wird der vom Browser gesendete MIME-Typ vom Betriebssystem gemeldet. Und genau deshalb ist, wie in der Frage angegeben, der vom Browser gemeldete MIME-Typ unzuverlässig.

62
user247702

Kip, ich habe einige Zeit damit verbracht, RFCs, MSDN und MDN zu lesen. Folgendes könnte ich verstehen. Wenn ein Browser auf eine Datei zum Hochladen stößt, überprüft er den ersten empfangenen Datenpuffer und führt anschließend einen Test durch. Diese Tests versuchen festzustellen, ob es sich bei der Datei um einen bekannten MIME-Typ handelt oder nicht. Wenn dieser MIME-Typ bekannt ist, wird er einfach weiter geprüft, für welchen bekannten MIME-Typ er gilt, und entsprechende Maßnahmen werden ergriffen. Ich denke, IE versucht dies zuerst, 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 Verzeichniseintrag zu lesen und dann zu ermitteln der Dateityp. Hier ist ein Link für FF https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIFile . Ich hätte noch mehr autoritative Informationen dazu.

10
Kumar

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. Die beste Möglichkeit, das Problem zu beheben, 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 Apache verwenden, um ihn serverseitig zu bestimmen.

5
johndodo

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

Beispielsweise:

HKEY_CLASSES_ROOT.Zip - ContentType

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

HKEY_CLASSES_ROOT\Mime\Database\Content Type

So rufen Sie die Standarderweiterung für einen bestimmten MIME-Typ ab.

Laut rfc1867 - Formularbasierter Dateiupload 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-stream ist ein bisschen wie ein blanket catch-all Bezeichner, wenn der Typ nicht abgeleitet werden kann .

0
smwikipedia

Ich stimme mit johndodo überein, 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 'application' konzentrieren. Wenn Ihre App auf PHP basiert, können Sie dies ganz einfach mit der Funktion explode () tun. Überprüfen Sie einfach die Dateierweiterung, um sicherzustellen, dass es sich um .Zip oder eine andere Komprimierung handelt, nach der Sie suchen!

0
Seul Shahkee