Les éléments <input> dont l'attribut type vaut "file" permettent à un utilisateur de sélectionner un ou plusieurs fichiers depuis leur appareil et de les uploader vers un serveur via un formulaire ou grâce à du code JavaScript via l'API File.

<input name="monFichier" type="file">

Valeur Une chaîne de caractères (DOMString) qui représente le chemin du fichier sélectionné.
Évènements change et input
Attributs pris en charge accept, multiple, required
Attributs IDL files et value
Méthodes select()

Valeur

L'attribut value contient une chaîne de caractères (DOMString) qui représente le chemin du/des fichier(s) sélectionné(s).

Note :
  1. Si plusieurs fichiers sont sélectionnés, la chaîne de caractères représente le chemin du premier fichier sélectionné. Il est possible d'accéder aux autres fichiers en JavaScript grâce à la propriété FileList.
  2. Si aucun fichier n'est sélectionné, la chaîne de caractères sera vide ("").
  3. La chaîne de caractères est préfixée avec C:\fakepath\ afin d'éviter la fuite d'informations sensibles concernant la structure des fichiers de l'utilisateur.

Utiliser <input type="file">

Un exemple simple

<form method="post" enctype="multipart/form-data">
 <div>
   <label for="file">Sélectionner le fichier à envoyer</label>
   <input type="file" id="file" name="file" multiple>
 </div>
 <div>
   <button>Envoyer</button>
 </div>
</form>

Ce fragment de code HTML produira le résultat suivant :

Note : Vous pouvez également trouver cet exemple sur GitHub — avec le code source et la démonstration.

Quel que soit l'appareil ou le système d'exploitation de l'utilisateur, l'élément <input type="file"> fournit un bouton qui ouvre un sélecteur de fichier permettant de choisir un fichier.

Lorsque l'attribut multiple est utilisé (comme dans l'exemple précédent), cela signifie que plusieurs fichiers peuvent être sélectionnés de façon simultanée. L'utilisateur doit alors pouvoir choisir plusieurs fichiers depuis le sélecteur de fichier (par exemple en maintenant la touche Shift ou Control puis en cliquant). Si on souhaite qu'un seul fichier puisse être envoyé, il suffit de ne pas utiliser l'attribut multiple.

Lorsqu'on envoie le formulaire de l'exemple, le nom de chaque fichier sera ajouté aux paramètres de l'URL de la façon suivante : ?file=fichier1.txt&file=fichier2.txt

Obtenir des informations sur les fichiers sélectionnés

Les fichiers sélectionnés peuvent être obtenus sous la forme d'un objet FileList renvoyé par la propriété HTMLInputElement.files de l'élement du DOM. Cet objet est une liste d'objets File. Un objet FileList se comporte comme un tableau et on peut donc consulter sa longueur (la propriété length) afin de connaître le nombre de fichiers sélectionnés.

Chaque objet File contient les informations suivantes :

  • name : le nom du fichier.
  • lastModified : un nombre représentant la date à laquelle le fichier a été modifié pour la dernière fois (sous la forme d'un horodatage UNIX).
  • lastModifiedDate : un objet Date qui représente la date et l'heure à laquelle le fichier a été modifié pour la dernière fois.
  • size : un nombre qui représente la taille du fichier en octets.
  • type : une chaîne de caractères (DOMString) qui représente le type MIME du fichier.
  • webkitRelativePath : une chaîne de caractères qui indique l'emplacement relatif du fichier par rapport au dossier de base indiqué par l'attribut webkitdirectory. Attention, cette fonctionnalité est non-standard et doit être utilisée avec attention.

Note : Dans la plupart des navigateurs récents, il est possible de récupérer et de modifier l'attribut IDL HTMLInputElement.files. Pour Firefox, cela a été ajouté avec la version 57 (cf. bug 1384030).

Restreindre les types de fichiers acceptés

Il arrive souvent qu'on souhaite sélectionner certains types de fichiers. Par exemple, si on souhaite fournir une image de profil, on restreindra probablemnt les formats à ceux des formats d'image compatibles pour le Web comme JPEG ou PNG.

Pour cela, on peut utiliser l'attribut accept afin d'indiquer les formats de fichier acceptés (sous la forme d'une liste d'extensions de fichier ou de types MIME séparés par des virgules). Par exemple :

  • accept="image/png" ou accept=".png" permettra de n'accepter que les fichiers PNG.
  • accept="image/png, image/jpeg" ou accept=".png, .jpg, .jpeg" permettra de n'accepter que les fichiers PNG ou JPEG.
  • accept="image/*" permettra d'accepter n'importe quel fichier dont le type MIME est image/* (pour de nombreux appareils mobiles, cette valeur permet d'utiliser l'appareil photo de l'appareil afin de prendre une photo qui sera utilisée comme fichier à envoyer).
  • accept=".doc,.docx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document" permettra d'accepter un fichier ressemblant à un document Word.

Prenons un exemple :

<form method="post" enctype="multipart/form-data">
  <div>
    <label for="profile_pic">Sélectionnez le fichier à utiliser</label>
    <input type="file" id="profile_pic" name="profile_pic"
          accept=".jpg, .jpeg, .png">
  </div>
  <div>
    <button>Envoyer</button>
  </div>
</form>

Voici le résultat produit :

Note : Vous pouvez également consulter cet exemple sur GitHub — voir le code source et la démonstration live.

Le résultat peut sembler similaire à l'exemple précédent mais lorsque vous essayer de sélectionner un fichier, vous verrez que le sélecteur ne permet de sélectionner que les fichiers du/des type(s) indiqué(s) (il peut y avoir certaines différences selons les navigateurs et les systèmes d'exploitation).

Screenshot of a macOS file picker dialog. Files other than JPEG are grayed-out and unselectable.

L'attribut accept ne permet pas de valider/contrôler le type réel du/des fichier(s) sélectionné(s). Il fournit simplement une indication au navigateur pour aider l'utilisateur à sélectionner les bons fichiers. Toutefois, dans la plupart des cas, l'utilisateur peut toujours choisir une option dans le sélecteur afin de pouvoir choisir un fichier d'un autre type.

Dans tous les cas (et comme pour les autres éléments envoyés au serveur), il est nécessaire de contrôler les données reçues par un mécanisme de validation côté serveur.

Exemples

Dans l'exemple qui suit, on présente sélecteur de fichiers plus avancé, qui tire parti des informations disponibles grâce à la propriété HTMLInputElement.files. On montre aussi quelques astuces.

Note : Le code source complet de cet exemple est disponible sur GitHub — file-example.html (voir la démonstration live associée). Nous n'expliquerons pas ici la feuille de style CSS mais plutôt le code JavaScript qui contient la logique.

Tout d'abord, voici le fragment de code HTML utilisé :

<form method="post" enctype="multipart/form-data">
  <div>
    <label for="image_uploads">Sélectionner des images à uploader (PNG, JPG)</label>
    <input type="file" id="image_uploads" name="image_uploads" accept=".jpg, .jpeg, .png" multiple>
  </div>
  <div class="preview">
    <p>Aucun fichier sélectionné pour le moment</p>
  </div>
  <div>
    <button>Envoyer</button>
  </div>
</form>

Pour l'instant, le fragment HTML ressemble à ce que nous avons déjà vu avant, rien de spécial.

Voyons maintenant le code JavaScript utilisé :

Pour les premières lignes du script, on récupère des références au formulaire et à l'élément <div> qui possède la classe .preview. Ensuite, on masque l'élément <input> car leur apparence peut être incohérente entre les navigateurs et qu'il est difficile de les mettre en forme. Cliquer sur l'élément <label> suffit à ouvrir le sélecteur et nous mettons donc en forme cet élément à la façon d'un bouton. Ainsi, l'utilisateur saura comment interagir avec le document pour uploader des fichiers.

var input = document.querySelector('input');
var preview = document.querySelector('.preview');

input.style.opacity = 0;

Note : La propriété opacity est utilisée pour masquer l'élément <input> plutôt que visibility: hidden ou display: none. En effet, avec ces derniers les technologies d'assistance (lecteurs d'écran par exemple) comprendraient que l'élément n'est pas interactif et ne peut pas être utilisé.

Ensuite, on ajoute un gestionnaire d'évènement à l'élément <input> afin de réaliser certaines actions lorsque sa valeur (c'est-à-dire les fichiers sélectionnés) change. Ici, le gestionnaire d'évènement appelle la fonction updateImageDisplay() que nous décrirons juste après.

input.addEventListener('change', updateImageDisplay);

À chaque fois que la fonction updateImageDisplay() est appelée :

  • On lance une boucle while afin de vider le contenu qui pourrait être dans l'élément <div> servant à la prévisualisation.
  • On récupère l'objet FileList qui contient les informations sur les fichiers sélectionnés et on le stocke dans une variable intitulée curFiles.
  • On vérifie si aucun fichier n'a été sélectionné (ce qui se traduit par vérifier si curFiles.length vaut 0). Si c'est le cas, on place un message dans le <div> de prévisualisation pour indiquer qu'aucun fichier n'a été sélectionné.
  • Si des fichiers ont été sélectionnés, on les parcourt afin d'afficher des informations sur ces fichiers dans l'élément <div>. Quelques notes :
    • On utilise une fonction validFileType() afin de vérifier si le fichier est bien du bon type (c'est-à-dire qu'il respecte les extensions d'image indiquées dans l'attribut accept).
      • Si c'est le cas :
        • On affiche le nom et la taille du fichier dans une liste à l'intérieur du <div> (obtenus à partir de curFiles[i].name et curFiles[i].size). La fonction returnFileSize() est utilisée ici afin d'afficher la taille de façon lisible (en octets, kilo-octets ou mega-octets plutôt que toujours en octets).
        • On génère un aperçu de l'image en appelant la méthode window.URL.createObjectURL(curFiles[i]) et en réduisant l'image grâce à du CSS puis on insère cette image dans la liste.
      • Si le type de fichier est invalide, on affiche un message dans la liste afin d'indiquer à l'utilisateur qu'il est nécessaire de sélectionner un autre type de fichier.
function updateImageDisplay() {
  while(preview.firstChild) {
    preview.removeChild(preview.firstChild);
  }

  var curFiles = input.files;
  if(curFiles.length === 0) {
    var para = document.createElement('p');
    para.textContent = 'No files currently selected for upload';
    preview.appendChild(para);
  } else {
    var list = document.createElement('ol');
    preview.appendChild(list);
    for(var i = 0; i < curFiles.length; i++) {
      var listItem = document.createElement('li');
      var para = document.createElement('p');
      if(validFileType(curFiles[i])) {
        para.textContent = 'File name ' + curFiles[i].name + ', file size ' + returnFileSize(curFiles[i].size) + '.';
        var image = document.createElement('img');
        image.src = window.URL.createObjectURL(curFiles[i]);

        listItem.appendChild(image);
        listItem.appendChild(para);

      } else {
        para.textContent = 'File name ' + curFiles[i].name + ': Not a valid file type. Update your selection.';
        listItem.appendChild(para);
      }

      list.appendChild(listItem);
    }
  }
}

La fonction validFileType() prend un objet File en entrée puis parcourt la liste des types de fichier autorisés pour les comparer à la propriété type du fichier. Si on trouve une correspondance (ce qui signifie que le type est bien autorisé), la fonction renvoie true, sinon, elle renvoie false.

var fileTypes = [
  'image/jpeg',
  'image/pjpeg',
  'image/png'
]

function validFileType(file) {
  for(var i = 0; i < fileTypes.length; i++) {
    if(file.type === fileTypes[i]) {
      return true;
    }
  }

  return false;
}

La fonction returnFileSize() prend en entrée un nombre d'octets (dans notre exemple, celui-ci provient de la propriété size du fichier) et le transforme en une chaîne de caractères plus compréhensible avec une taille en octets/Ko/Mo.

function returnFileSize(number) {
  if(number < 1024) {
    return number + ' octets';
  } else if(number > 1024 && number < 1048576) {
    return (number/1024).toFixed(1) + ' Ko';
  } else if(number > 1048576) {
    return (number/1048576).toFixed(1) + ' Mo';
  }
}

Et voici le résultat :

Spécifications

Spécification État Commentaires
HTML Living Standard
La définition de '<input type="file">' dans cette spécification.
Standard évolutif Définition initiale.
HTML 5.1
La définition de '<input type="file">' dans cette spécification.
Recommendation Définition initiale.

Compatibilité des navigateurs

Fonctionnalité Chrome Edge Firefox (Gecko) Internet Explorer Opera Safari
Support simple 1.0 ? 1.0 (1.7 ou moins) (Oui) 1.0 1.0
Fonctionnalité Android Chrome pour Android Edge Firefox Mobile (Gecko) IE Mobile Opera Mobile iOS WebKit
(Safari/Chrome/Firefox/etc)
Support simple (Oui) (Oui) (Oui) 4.0 (4.0) (Oui) (Oui) (Oui)

Voir aussi

Étiquettes et contributeurs liés au document

Étiquettes : 
 Contributeurs à cette page : SphinxKnight, gnoxr, daufinsyd
 Dernière mise à jour par : SphinxKnight,