J'ai une application Web où l'utilisateur doit télécharger un fichier .Zip. Côté serveur, je vérifie le type MIME du fichier téléchargé, pour m'assurer qu'il est application/x-Zip-compressed
ou application/Zip
.
Cela a bien fonctionné pour moi sur Firefox et IE. Cependant, lorsqu'un collègue l'a testé, cela a échoué pour lui sur Firefox (le type de mime envoyé était quelque chose comme "application/octet-stream
") mais fonctionnait sur Internet Explorer. Nos configurations semblent identiques: IE8, FF 3.5.1 avec tous les modules complémentaires désactivés, Win XP SP3, WinRAR installé en tant que fichier natif .Zip gestionnaire (je ne sais pas si c'est pertinent).
Donc ma question est: Comment le navigateur détermine-t-il quel type de mime envoyer?
Remarque: je sais que le type MIME est envoyé par le navigateur et, par conséquent, peu fiable. Je le vérifie simplement pour plus de 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).
Chrome (version 38 au moment de l'écriture) a 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=17 (kPrimaryMappings
et 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
. Ceci est dû au fait .csv
n'est pas spécifié dans la première liste codée en dur, le navigateur revient donc au registre système. HKEY_CLASSES_ROOT\.csv
a une valeur nommée Content Type
défini sur application/vnd.ms-Excel
.
Toujours en utilisant le même exemple, le navigateur signalera application/vnd.ms-Excel
. Je pense qu'il est raisonnable de supposer qu'Internet Explorer (version 11 au moment de l'écriture) 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.
Comme indiqué dans le code Chrome Chrome, Firefox (version 32 au moment de l'écriture) fonctionne de la même manière. fichier uriloader\exthandler\nsExternalHelperAppService.cpp
, méthode 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
Les listes codées en dur viennent plus tôt dans le fichier, quelque part près de la ligne 441. Vous recherchez defaultMimeEntries
et extraMimeEntries
.
Avec mon profil actuel, le navigateur signalera text/csv
parce qu'il y a une entrée pour cela dans mimeTypes.rdf
(point 2 de la liste ci-dessus). Avec un nouveau profil, qui n'a pas cette entrée, le navigateur signalera application/vnd.ms-Excel
(point 3 de la liste).
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 signalé par le navigateur n'est pas fiable.
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 sur celui-ci. Ces tests tentent de déterminer si le fichier est un type MIME connu ou non, et s'il est de type MIME connu, il le testera simplement pour quel type MIME connu et prendra des mesures en conséquence. Je pense que IE essaie de le faire d'abord 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 je pouvais comprendre, c'est qu'il essaie de lire les informations sur les fichiers à 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 . Je voudrais toujours avoir plus d'informations faisant autorité à ce sujet.
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 façon de le déterminer. Cependant, les navigateurs envoient le nom d'origine (y compris l'extension) du fichier. Par conséquent, la meilleure façon de résoudre le problème consiste à inspecter l'extension du fichier au lieu du type MIME.
Si vous avez toujours besoin du type mime, vous pouvez utiliser vos propres mime.types d'Apache pour le déterminer côté serveur.
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 consultant 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.
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 frappe du système d'exploitation) ou en tant que flux d'application/octet.
Donc, ma compréhension est, application/octet-stream
est un peu comme un blanket catch-all
identifiant si le type ne peut pas être déduit .
Je suis d'accord avec johndodo, il y a tellement de variables qui rendent les types MIME envoyés par les navigateurs peu fiables. Je voudrais exclure les sous-types reçus et me concentrer uniquement sur le type comme "application". si votre application est basée sur php, vous pouvez facilement le faire en utilisant la fonction explode (). en outre, 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!