Un type MIME est un mécanisme utilisé pour indiquer le type de contenu d'un fichier transmis sur Internet (et ce de multiples façons), à l'aide d'un format très simple : type/sous-type
.
Historiquement, MIME signifie Multipurpose Internet Mail Extensions, et provient donc du monde de l'e-mail. Mais on le retrouve partout sur le web, et en particulier avec le protocole HTTP qui fait fonctionner la navigation de tous les jours.
Parmi les exemples les plus célèbres :
Type MIME | Format de fichier |
---|---|
text/plain | Texte simple |
text/html | Document HTML |
image/gif | Image GIF |
image/png | Image PNG |
image/jpeg | Image JPEG |
image/svg+xml | Image SVG |
audio/mp3 | Son MP3 |
video/mp4 | Vidéo MP4 |
application/javascript | Code JavaScript |
application/json | JSON |
application/pdf | Document PDF |
font/woff | Police WOFF |
font/woff2 | Police WOFF v2 |
application/vnd.ms-excel | Microsoft Excel |
application/x-7z-compressed | Compression au format 7zip |
Et ainsi de suite : vous saisissez le concept. Une liste assez impressionnante de types reconnus est tenue à jour par l'IANA Internet Assigned Numbers Authority.
Les formats propriétaires peuvent être préfixés par .vnd
comme vendor, d'autres par x-
ce qui permet une certaine liberté d'invention. Flash s'en souvient avec application/x-shockwave-flash
.
On peut aussi ajouter une précision supplémentaire sur l'encodage text/html; charset=UTF-8
pour un document HTML en UTF-8, ou video/ogg; codecs="theora, vorbis"
pour de la vidéo dont le conteneur est Ogg et dont les codecs internes sont Theora pour la vidéo combiné à Vorbis pour l'audio. Cela engendre une grande possibilité de tests et de combinaisons : https://cconcolato.github.io/media-mime-support/. En JavaScript, la méthode canPlayType()
qui équipe les éléments média (audio
, video
) indique si le navigateur pourrait décoder le format qui lui est proposé.
Lorsqu'un type est inconnu on utilise application/octet-stream
, ce qui d'un point de vue navigateur web va simplement déclencher un téléchargement brut.
Pourquoi ?
Annoncer un type de contenu est important pour permettre au programme devant le recevoir (ex: le navigateur) de bien savoir s'il est en mesure d'en faire quelque chose d'utile : l'afficher de manière brute, ou le passer au module adéquat, par exemple une bibliothèque de décodage d'image PNG pour une image PNG, la bibliothèque ffmpeg pour les vidéos, etc. On ne se fie donc pas à l'extension du fichier, comme c'est le cas par défaut sur la plupart des systèmes d'exploitation.
Côté navigateur
Les requêtes HTTP contiennent à la fois, à l'envoi et à la réception, des instructions exploitant les types MIME. Vous pouvez les visualiser facilement dans les outils de développement (devtools, F12, etc), onglet Réseau ou Network.
Envoi
À l'envoi le navigateur annonce au serveur ce qu'il peut reconnaître, parmi autres informations, via l'en-tête Accept
.
GET / HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7
On remarquera aussi dans ce dernier exemple qu'il sait reconnaître des algorithmes de compression (gzip, deflate, brotli), et qu'il indique le code langue préféré.
Réception
À la réception, le navigateur reçoit du serveur le type MIME du fichier livré, que ce soit pour la page HTML, ses images, ses médias, ses ressources CSS, JavaScript, la totale. Si un type ne correspond pas au contenu réel, cela peut engendrer un refus d'interprétation, notamment par mesure de sécurité.
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 11 Oct 2023 20:07:36 GMT
Content-Type: text/html; charset=UTF-8
Content-Encoding: gzip
Sécurité : le MIME éthique
Ainsi, on ne se base pas sur l'extension des fichiers qui peut facilement être modifiée. Cela fait partie également des directives de sécurité que l'on peut véhiculer via HTTP : voir Tour d’horizon sur HTTPS et les en-têtes de sécurité avec l'en-tête X-Content-Type-Options "nosniff"
indiquant au navigateur qu'il ne doit pas essayer de "deviner" un type non indiqué.
Le sniffing et la rétro-compatibilité ne se font pas au hasard, il existe une spécifiaction précise et à jour pour mener à bien cette opération délicate : MIME Sniffing.
Ainsi, on pourra y découvrir que pour des raisons historique, JavaScript peut être reconnu par tous les types MIME suivants :
application/ecmascript
application/javascript
application/x-ecmascript
application/x-javascript
text/ecmascript
text/javascript
text/javascript1.0
text/javascript1.1
text/javascript1.2
text/javascript1.3
text/javascript1.4
text/javascript1.5
text/jscript
text/livescript
text/x-ecmascript
text/x-javascript
Ouf.
Back-end
L'envoi des en-têtes se fait souvent de manière transparente, même lorsqu'on développe, par le serveur web car celui-ci est déjà bien configuré par défaut. Sinon, on peut les ajouter ou les modifier grâce à la plupart des langages back-end, tels que PHP et sa fonction header :
<?php
header('Content-Type: text/html');
// ...
Dans les e-mails
Puisque c'est du protocole d'échange d'e-mails qu'est issue cette technique, mentionnons que les codes sources des e-mails (que vous pouvez très simplement consulter dans votre client de messagerie favori, Ctrl+U dans Mozilla Thunderbird) exposent assez clairement les types MIME par des instructions Content-Type
. Tout comme HTTP.
Vous retrouverez ainsi dans les en-têtes de début du mail une déclaration telle que :
MIME-Version: 1.0
Puis à quelques encablures, annonçant la partie en texte brut :
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Puis, encore plus loin, l'équivalent pour la version mise en forme avec HTML :
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Et enfin, en préambule de chacune des pièces jointes :
Content-Type: application/pdf; name="document.pdf"
Content-Disposition: attachment; filename="document.pdf"
Content-Transfer-Encoding: base64
Suivi de tout le contenu du fichier encodé en base64. Basique mais efficace.
Type composé multipart
Le type multipart/form-data
est pensé pour gérer des formulaires web transmettant plusieurs formats de données simultanément, et notamment lorsqu'il y a un fichier joint présent par un champ <input type="file">
. Ainsi il faudra déclarer le formulaire avec un attribut enctype
:
<form method="post" enctype="multipart/form-data">
<input type="text" name="unchamptexte">
<input type="file" name="unfichier">
<input type="submit" value="Envoyer">
</form>
(Cet exemple n'est pas exhaustif, volontairement simplifié pour l'explication, pensez à le rendre propre et accessible avec des balises <label>
).
Vous pourrez ensuite analyser l'envoi, toujours dans l'onglet Réseau de vos outils de développement, en examinant la requête HTTP. Celle-ci comprendra bien une déclaration Content-Type: multipart/form-data
suivi d'un paramètre boundary
indiquant quelle chaîne de caractère va séparer les différentes entités empaquetées dans la requête.
Content-Type: multipart/form-data; boundary=---------------------------xxx
Content-Length: 436
-----------------------------xxx
Content-Disposition: form-data; name="unchamptexte"
Besser e stick Brot im Sack, as e Fedder am Huet.
-----------------------------xxx
Content-Disposition: form-data; name="unfichier"; filename="hopla.txt"
Content-Type: text/plain
Lorem Elsass ipsum dui kuglopf geht's Pellentesque dolor mollis schneck semper so knepfle Pfourtz !
Le Secret du MIME n'en est plus un désormais !
Commenter
Vous devez être inscrit et identifié pour utiliser cette fonction.
Connectez-vous (déjà inscrit)
Pas encore inscrit ? C'est très simple et gratuit.