Comment le type MIME d'un fichier téléchargé est-il déterminé par le navigateur?

87

J'ai une application Web dans laquelle l'utilisateur doit télécharger un fichier .zip. Du côté serveur, je vérifie le type mime du fichier téléchargé, pour m'assurer qu'il estapplication/x-zip-compressed ou application/zip.

Cela a bien fonctionné pour moi sur Firefox et IE. Cependant, lorsqu'un collègue l'a testé, il a échoué pour lui sur Firefox (le type mime envoyé était quelque chose comme " application/octet-stream") mais a fonctionné sur Internet Explorer. Nos configurations semblent être identiques: IE8, FF 3.5.1 avec tous les modules désactivés, Win XP SP3, WinRAR installé en tant que gestionnaire de fichiers .zip natif (je ne sais pas si c'est pertinent).

Ma question est donc: comment le navigateur détermine-t-il quel type de mime envoyer?

Veuillez noter: je sais que le type mime est envoyé par le navigateur et donc peu fiable. Je le vérifie simplement par commodité - principalement pour donner un message d'erreur plus convivial que ceux que vous obtenez en essayant d'ouvrir un fichier non zip en tant que fichier zip, et pour éviter de charger les bibliothèques de fichiers zip (vraisemblablement lourdes).

Kip
la source
application / octet-stream désigne un fichier binaire. Vous devriez pouvoir obtenir l'extension du fichier pour voir s'il s'agit d'un fichier zip. Juste pour clarifier, cela a-t-il fonctionné pour vous sur FF, mais pas pour votre collègue?
Kevin Crowell le
oui, cela a fonctionné pour moi dans les deux navigateurs
Kip
jetez un oeil à input/@formenctypeou form/@enctypeattributs
tuxSlayer

Réponses:

72

Chrome

Chrome (version 38 au moment de la rédaction) dispose de 3 façons de déterminer le type MIME et le fait dans un certain ordre. L'extrait ci-dessous provient du fichier src/net/base/mime_util.cc, méthode 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.

Les listes codées en dur viennent un peu plus tôt dans le fichier: https://cs.chromium.org/chromium/src/net/base/mime_util.cc?l=170 ( kPrimaryMappingset kSecondaryMappings).

Un exemple: lors du téléchargement d'un fichier CSV à partir d'un système Windows avec Microsoft Excel installé, Chrome le signalera comme application/vnd.ms-excel. C'est parce que .csvn'est pas spécifié dans la première liste codée en dur, de sorte que le navigateur revient au registre système. HKEY_CLASSES_ROOT\.csva une valeur nommée Content Typedéfinie sur application/vnd.ms-excel.

Internet Explorer

Toujours en utilisant le même exemple, le navigateur fera un rapport application/vnd.ms-excel. Je pense qu'il est raisonnable de supposer Internet Explorer (version 11 au moment de la rédaction) utilise le registre. Peut-être qu'il utilise également une liste codée en dur comme Chrome et Firefox, mais sa nature de source fermée le rend difficile à vérifier.

Firefox

Comme indiqué dans le code Chrome, Firefox (version 32 au moment de la rédaction) fonctionne de la même manière. Extrait de fichier uriloader\exthandler\nsExternalHelperAppService.cpp, méthodensExternalHelperAppService::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

Les listes codées en dur viennent plus tôt dans le fichier, quelque part près de la ligne 441. Vous recherchez defaultMimeEntriesetextraMimeEntries .

Avec mon profil actuel, le navigateur fera un rapport text/csvcar il y a une entrée pour lui dans mimeTypes.rdf(élément 2 dans la liste ci-dessus). Avec un nouveau profil, qui n'a pas cette entrée, le navigateur signaleraapplication/vnd.ms-excel (élément 3 dans la liste).

Sommaire

Les listes codées en dur dans les navigateurs sont assez limitées. Souvent, le type MIME envoyé par le navigateur sera celui signalé par le système d'exploitation. Et c'est exactement pourquoi, comme indiqué dans la question, le type MIME indiqué par le navigateur n'est pas fiable.

user247702
la source
1
Merci! avez-vous un lien vers la liste codée en dur dans la source chrome?
Kip
@Kip ouais, j'ai ajouté un lien. Firefox ne semble pas avoir de navigateur de code source en ligne (officiel), j'ai dû le télécharger depuis leur serveur FTP.
user247702
Avoir le MIME comme ms-excel pour CSV est ennuyeux, demandez-vous pourquoi il ne figure pas dans la liste codée en dur.
Kris
Ce serait bien de savoir s'il y a eu des mises à jour dans la détection de type mime depuis 2014.
Vitaly Isaev
1
@VitalyIsaev un coup d'œil rapide sur le code Chrome montre que cela n'a pas changé depuis 2014.
user247702
12

Kip, j'ai passé du temps à lire les RFC, MSDN et MDN. Voici ce que j'ai pu comprendre. Lorsqu'un navigateur rencontre un fichier à télécharger, il examine le premier tampon de données qu'il reçoit, puis exécute un test dessus. Ces tests tentent de déterminer si le fichier est d'un type mime connu ou non, et s'il s'agit d'un type mime connu, il le testera simplement plus avant pour quel type mime connu et prendra les mesures nécessaires. Je pense que IE essaie de faire cela en premier plutôt que de simplement déterminer le type de fichier à partir de l'extension. Cette page explique cela pour IE http://msdn.microsoft.com/en-us/library/ms775147%28v=vs.85%29.aspx . Pour Firefox, ce que j'ai pu comprendre, c'est qu'il essaie de lire les informations de fichier à partir du système de fichiers ou de l'entrée de répertoire, puis détermine le type de fichier. Voici un lien pour FF https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIFile. J'aimerais toujours avoir des informations plus fiables à ce sujet.

Kumar
la source
8

Cela dépend probablement du système d'exploitation et peut-être du navigateur, mais sous Windows, le type MIME pour une extension de fichier donnée peut être trouvé en regardant dans le registre sous HKCR:

Par exemple:

HKEY_CLASSES_ROOT.zip - ContentType

Pour passer de MIME à l'extension de fichier, vous pouvez regarder les clés sous

HKEY_CLASSES_ROOT \ Mime \ Database \ Content Type

Pour obtenir l'extension par défaut pour un type MIME particulier.

Michael A. McCloskey
la source
Merci. malheureusement, pour moi et mon collègue, cela semble être correct dans notre registre. Je suppose que c'est pourquoi cela a fonctionné dans IE pour lui, mais FF l'obtient différemment ... eh bien :(
Kip
5

Bien que ce ne soit pas une réponse à votre question, cela résout le problème que vous essayez de résoudre. YMMV.

Comme vous l'avez écrit, le type mime n'est pas fiable car chaque navigateur a sa manière de le déterminer. Cependant, les navigateurs envoient le nom d'origine (y compris l'extension) du fichier. La meilleure façon de résoudre le problème est donc d'inspecter l'extension du fichier au lieu du type MIME.

Si vous avez toujours besoin du type mime, vous pouvez utiliser les types mime.types de votre propre apache pour le déterminer côté serveur.

johndodo
la source
1
Voulez-vous élaborer? D'après mon expérience, les navigateurs envoient toujours le nom de fichier d'origine correct (avec l'extension) tandis que les types MIME varient considérablement. Alors oui, je dirais que c'est beaucoup plus fiable.
johndodo
Correct. Je voulais dire que l'utilisateur final peut mettre n'importe quelle extension, quel que soit le type réel, donc il ne devrait pas lui faire confiance.
Djizeus
C'est vrai, mais peu importe si vous utilisez l'extension ou le type MIME - vous ne devriez jamais faire confiance à l'entrée fournie par l'utilisateur. Mais OP a déclaré explicitement qu'il est conscient de ce problème, donc cela ne fait pas partie de cette question. Btw, j'apprécierais que vous supprimiez le vote défavorable (je suppose que cela vient de vous).
johndodo
Vous avez raison, n'a pas fait attention au pas dans la question, mon mal. Je peux annuler mon vote mais vous devrez modifier la réponse pour cela (imposé par le système) ...
Djizeus
Ouais, je suis d'accord avec johndodo. Comme Stijn l'a expliqué dans sa réponse ci-dessus, Chrome et Firefox vérifient d'abord l'extension. Ils font la même chose à la fin.
Jenix le
0

Je suis d'accord avec johndodo, il y a tellement de variables qui rendent les types mime envoyés par les navigateurs peu fiables. J'exclurais les sous-types qui sont reçus et me concentrerais simplement sur le type comme «application». si votre application est basée sur php, vous pouvez facilement le faire en utilisant la fonction explode (). de plus, vérifiez simplement l'extension du fichier pour vous assurer qu'il s'agit bien de .zip ou de toute autre compression que vous recherchez!

Seul Shahkee
la source
0

Selon rfc1867 - Téléchargement de fichier basé sur un formulaire en HTML :

Chaque partie doit être étiquetée avec un type de contenu approprié si le type de support est connu (par exemple, déduit de l'extension de fichier ou des informations de typage du système d'exploitation) ou comme application / flux d'octets.

Donc, je crois comprendre, application/octet-streamc'est un peu comme un blanket catch-allidentificateur si le type ne peut pas être déduit .

smwikipedia
la source
oui, je comprends tout cela. la question était de savoir comment le navigateur en déduit.
Kip le
Cela vaut la peine de savoir, non? Si application/octet-streamc'est le fourre-tout, alors une autre approche serait de faire confiance au navigateur s'il a pu faire une estimation, et de faire vos propres tests côté serveur si vous obtenez application/octet-stream.
MikeBeaton