In che modo il tipo MIME di un file caricato viene determinato dal browser?


87

Ho un'app Web in cui l'utente deve caricare un file .zip. Sul lato server, sto controllando il tipo MIME del file caricato, per assicurarmi che sia application/x-zip-compressedo application/zip.

Questo ha funzionato bene per me su Firefox e IE. Tuttavia, quando un collega l'ha testato, ha fallito su Firefox (il tipo MIME inviato era qualcosa come " application/octet-stream") ma ha funzionato su Internet Explorer. Le nostre configurazioni sembrano essere identiche: IE8, FF 3.5.1 con tutti i componenti aggiuntivi disabilitati, Win XP SP3, WinRAR installato come gestore di file .zip nativo (non sono sicuro se sia rilevante).

Quindi la mia domanda è: in che modo il browser determina quale tipo MIME inviare?

Nota: so che il tipo MIME viene inviato dal browser e, quindi, inaffidabile. Lo sto solo controllando per comodità, principalmente per fornire un messaggio di errore più amichevole di quelli che si ottengono cercando di aprire un file non zip come file zip e per evitare di caricare le librerie di file zip (presumibilmente pesanti).


application / octet-stream designa un file binario. Dovresti essere in grado di ottenere l'estensione del file per vedere se si tratta di un file zip. Giusto per chiarire, ha funzionato per te su FF, ma non per il tuo collega?
Kevin Crowell,

sì, ha funzionato per me in entrambi i browser
Kip

dai un'occhiata input/@formenctypeo form/@enctypeattributi
tuxSlayer

Risposte:


72

Cromo

Chrome (versione 38 al momento della scrittura) ha 3 modi per determinare il tipo MIME e lo fa in un certo ordine. Lo snippet di seguito è da file src/net/base/mime_util.cc, metodo 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.

Gli elenchi hard-coded sono un po 'prima nel file: https://cs.chromium.org/chromium/src/net/base/mime_util.cc?l=170 ( kPrimaryMappingsekSecondaryMappings ).

Un esempio: quando si carica un file CSV da un sistema Windows con Microsoft Excel installato, Chrome lo segnalerà come application/vnd.ms-excel. Questo perché .csvnon è specificato nel primo elenco hardcoded, quindi il browser torna al registro di sistema. HKEY_CLASSES_ROOT\.csvha un valore denominato Content Typeche è impostato suapplication/vnd.ms-excel .

Internet Explorer

Sempre usando lo stesso esempio, il browser riporterà application/vnd.ms-excel. Penso che sia ragionevole presumere che Internet Explorer (versione 11 al momento della scrittura) utilizzi il registro. Forse fa anche uso di un elenco hard-coded come Chrome e Firefox, ma la sua natura closed source lo rende difficile da verificare.

Firefox

Come indicato nel codice Chrome, Firefox (versione 32 al momento della scrittura) funziona in modo simile. Snippet da file uriloader\exthandler\nsExternalHelperAppService.cpp, metodonsExternalHelperAppService::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

Gli elenchi hard-coded sono presenti in precedenza nel file, da qualche parte vicino alla riga 441. Stai cercando defaultMimeEntriese extraMimeEntries.

Con il mio profilo attuale, il browser segnalerà text/csvperché c'è una voce per esso inmimeTypes.rdf (elemento 2 nell'elenco sopra). Con un nuovo profilo, che non ha questa voce, il browser segnaleràapplication/vnd.ms-excel (elemento 3 nell'elenco).

Sommario

Gli elenchi hard-coded nei browser sono piuttosto limitati. Spesso il tipo MIME inviato dal browser sarà quello segnalato dal sistema operativo. Ed è proprio per questo che, come affermato nella domanda, il tipo MIME segnalato dal browser non è affidabile.


1
Grazie! hai un link all'elenco hard-coded nella sorgente di Chrome?
Kip

@Kip sì, ho aggiunto un collegamento. Firefox non sembra avere un browser del codice sorgente online (ufficiale), ho dovuto scaricarlo dal loro server FTP.
user247702

Avere MIME come ms-excel per CSV è fastidioso, chiediti perché non è nell'elenco hardcoded.
Kris

Sarebbe bello sapere se ci sono stati alcuni aggiornamenti nel rilevamento del tipo MIME dal 2014.
Vitaly Isaev,

1
@VitalyIsaev una rapida occhiata al codice Chrome mostra che questo non è cambiato dal 2014.
user247702

12

Kip, ho passato un po 'di tempo a leggere RFC, MSDN e MDN. Ecco cosa ho potuto capire. Quando un browser trova un file da caricare, esamina il primo buffer di dati che riceve e quindi esegue un test su di esso. Questi test cercano di determinare se il file è un tipo MIME noto o meno, e se il tipo MIME conosciuto lo testerà ulteriormente per quale tipo MIME conosciuto e agirà di conseguenza. Penso che IE cerchi di farlo prima piuttosto che determinare semplicemente il tipo di file dall'estensione. Questa pagina spiega questo per IE http://msdn.microsoft.com/en-us/library/ms775147%28v=vs.85%29.aspx . Per Firefox, quello che ho potuto capire è che cerca di leggere le informazioni sul file dal filesystem o dalla voce della directory e quindi determina il tipo di file. Ecco un collegamento per FF https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIFile. Mi piacerebbe comunque avere informazioni più autorevoli su questo.


8

Probabilmente dipende dal sistema operativo e dal browser, ma su Windows il tipo MIME per una determinata estensione di file può essere trovato cercando nel registro sotto HKCR:

Per esempio:

HKEY_CLASSES_ROOT.zip - ContentType

Per passare da MIME all'estensione del file, puoi guardare i tasti sotto

HKEY_CLASSES_ROOT \ Mime \ Database \ Content Type

Per ottenere l'estensione predefinita per un particolare tipo MIME.


Grazie. sfortunatamente, sia per me che per il mio collega questo sembra essere corretto nel nostro registro. Immagino sia per questo che ha funzionato in IE per lui, ma FF lo sta ottenendo in modo diverso in qualche modo ... vabbè :(
Kip

5

Sebbene questa non sia una risposta alla tua domanda, risolve il problema che stai cercando di risolvere. YMMV.

Come hai scritto, il tipo MIME non è affidabile poiché ogni browser ha il suo modo di determinarlo. Tuttavia, i browser inviano il nome originale (inclusa l'estensione) del file. Quindi il modo migliore per affrontare il problema è controllare l'estensione del file invece del tipo MIME.

Se hai ancora bisogno del tipo mime, puoi usare il tuo mime.types di apache per determinarlo lato server.


1
Ti va di elaborare? Nella mia esperienza i browser inviano sempre il nome file originale corretto (con estensione) mentre i tipi MIME variano notevolmente. Quindi sì, direi che è molto più affidabile.
johndodo

Corretta. Volevo dire che l'utente finale può inserire qualsiasi estensione, indipendentemente dal tipo effettivo, quindi non dovrebbe essere attendibile.
Djizeus

Questo è vero, ma non importa se usi l'estensione o il tipo MIME: non dovresti mai fidarti dell'input fornito dall'utente. Ma OP ha dichiarato esplicitamente di essere a conoscenza di questo problema, quindi questo non fa parte di questa domanda. A proposito, ti sarei grato se avessi rimosso il voto negativo (presumo che provenisse da te).
johndodo

Hai ragione, non ho prestato attenzione al non in questione, colpa mia. Posso annullare il mio voto ma dovrai modificare la risposta per questo (imposta dal sistema) ...
Djizeus

Sì, sono d'accordo con johndodo. Come ha spiegato Stijn nella sua risposta sopra, Chrome e Firefox controllano prima l'estensione. Stanno facendo la stessa cosa alla fine.
Jenix

0

Sono d'accordo con johndodo, ci sono così tante variabili che rendono inaffidabili i tipi MIME inviati dai browser. Escluderei i sottotipi ricevuti e mi concentrerei solo sul tipo come "applicazione". se la tua app è basata su php, puoi farlo facilmente usando la funzione explode (). inoltre, controlla l'estensione del file per assicurarti che sia .zip o qualsiasi altra compressione che stai cercando!


0

Secondo rfc1867 - Caricamento di file basato su modulo in HTML :

Ogni parte deve essere etichettata con un tipo di contenuto appropriato se il tipo di supporto è noto (ad esempio, dedotto dall'estensione del file o dalle informazioni di digitazione del sistema operativo) o come application / ottetto-stream.

Quindi la mia comprensione è, application/octet-streamè un po 'come un blanket catch-allidentificatore se il tipo non può essere dedotto .


si, capisco tutto questo. la domanda era come deduce il browser.
Kip

Vale la pena saperlo, giusto? Se application/octet-streamè il tutto sommato, un altro approccio sarebbe quello di fidarsi del browser se è stato in grado di fare un'ipotesi, e di eseguire i propri test lato server se si ottiene application/octet-stream.
MikeBeaton
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.