Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Utiliser des fichiers à partir d'applications web

En utilisant l'API de manipulation de fichier, qui a été ajoutée au DOM dans le HTML5, il est maintenant possible depuis une application web de proposer à l'utilisateur de sélectionner des fichiers locaux, puis d'en lire le contenu. Cette sélection peut s'effectuer soit en utilisant un élément HTML <input>, soit avec un glisser-déposer.

If you want to use the DOM File API from extensions or other browser chrome code, you can; in fact, there are some additional features to be aware of. See Using the DOM File API in chrome code for details.

Accèder au(x) fichier(s) sélectionné(s)

Considèrons ce code HTML:

<input type="file" id="input">

L'API File permet d'accèder à la FileList contenant les objets File qui correspondent aux fichiers selectionnés par l'utilisateur.

Si l'utilisateur ne sélectionne qu'un seul fichier, on considèrera uniquement le premier élèment de la FileList.

Pour accèder à un des fichiers sélectionnés grâce à une sélection classique sur le DOM :

var fichierSelectionne = document.getElementById('input').files[0];

Pour accèder à un des fichiers sélectionnés en utilisant un selecteur jQuery :

var fichierSelectionne = $('#input')[0].files[0];

If you get a "files is undefined" error: you didn't select the right HTML element, forgetting that a jQuery selector returns a list of matched DOM elements. So get the DOM element to call the "files" method on it.

Accessing selected file(s) on a change event

It is also possible (but not mandatory) to access the FileList through the change event:

<input type="file" id="input" onchange="handleFiles(this.files)">

When the user selects a file, the handleFiles() function gets called with a FileList object containing File objects representing the files selected by the user.

If you want to let the user select multiple files, simply use the multiple attribute on the input element:

<input type="file" id="input" multiple onchange="handleFiles(this.files)">

In this case, the file list passed to the handleFiles() function contains one File object for each file the user selected.

Dynamically adding a change listener

If your input field was created using a JavaScript library such as jQuery, you'll need to use element.addEventListener() to add the change event listener, like this:

var inputElement = document.getElementById("inputField");
inputElement.addEventListener("change", handleFiles, false);
function handleFiles() {
  var fileList = this.files; /* now you can work with the file list */
}

Note that in this case, the handleFiles() function looks up the file list instead of accepting a parameter, since event listeners added in this way can't accept an input parameter.

Getting information about selected file(s)

The FileList object provided by the DOM lists all the files selected by the user, each specified as a File object. You can determine how many files the user selected by checking the value of the file list's length attribute:

var numFiles = files.length;

Individual File objects can be retrieved by simply accessing the list as an array:

for (var i = 0, numFiles = files.length; i < numFiles; i++) {
  var file = files[i];
  ..
}

This loop iterates over all the files in the file list.

There are three attributes provided by the File object that contain useful information about the file.

name
The file's name as a read-only string. This is just the file name, and does not include any path information.
size
The size of the file in bytes as a read-only 64-bit integer.
type
The MIME type of the file as a read-only string, or "" if the type couldn't be determined.

Example: Showing file(s) size

The following example shows a possible use of the size property:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>File(s) size</title>
<script>
function updateSize() {
  var nBytes = 0,
      oFiles = document.getElementById("uploadInput").files,
      nFiles = oFiles.length;
  for (var nFileId = 0; nFileId < nFiles; nFileId++) {
    nBytes += oFiles[nFileId].size;
  }
  var sOutput = nBytes + " bytes";
  // optional code for multiples approximation
  for (var aMultiples = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"], nMultiple = 0, nApprox = nBytes / 1024; nApprox > 1; nApprox /= 1024, nMultiple++) {
    sOutput = nApprox.toFixed(3) + " " + aMultiples[nMultiple] + " (" + nBytes + " bytes)";
  }
  // end of optional code
  document.getElementById("fileNum").innerHTML = nFiles;
  document.getElementById("fileSize").innerHTML = sOutput;
}
</script>
</head>

<body onload="updateSize();">
<form name="uploadForm">
<p><input id="uploadInput" type="file" name="myFiles" onchange="updateSize();" multiple> selected files: <span id="fileNum">0</span>; total size: <span id="fileSize">0</span></p>
<p><input type="submit" value="Send file"></p>
</form>
</body>
</html>

Using hidden file input elements using the click() method

Starting in Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1), you can hide the admittedly ugly file <input> element and present your own interface for opening the file picker and displaying which file or files the user has selected. You can do this by styling the input element with display:none and calling the click() method on the <input> element.

Consider this HTML:

<input type="file" id="fileElem" multiple accept="image/*" style="display:none" onchange="handleFiles(this.files)">
<a href="#" id="fileSelect">Select some files</a>

The code that handles the click event can look like this:

var fileSelect = document.getElementById("fileSelect"),
  fileElem = document.getElementById("fileElem");

fileSelect.addEventListener("click", function (e) {
  if (fileElem) {
    fileElem.click();
  }
  e.preventDefault(); // prevent navigation to "#"
}, false);

Obviously you can style the new button for opening the file picker as you wish.

Selecting files using drag and drop

You can also let the user drag and drop files into your web application.

The first step is to establish a drop zone. Exactly what part of your content will accept drops may vary depending on the design of your application, but making an element receive drop events is easy:

var dropbox;

dropbox = document.getElementById("dropbox");
dropbox.addEventListener("dragenter", dragenter, false);
dropbox.addEventListener("dragover", dragover, false);
dropbox.addEventListener("drop", drop, false);

In this example, we're turning the element with the ID dropbox into our drop zone. This is done by adding listeners for the dragenter, dragover, and drop events.

We don't actually need to do anything with the dragenter and dragover events in our case, so these functions are both simple. They just stop propagation of the event and prevent the default action from occurring:

function dragenter(e) {
  e.stopPropagation();
  e.preventDefault();
}

function dragover(e) {
  e.stopPropagation();
  e.preventDefault();
} 

The real magic happens in the drop() function:

function drop(e) {
  e.stopPropagation();
  e.preventDefault();

  var dt = e.dataTransfer;
  var files = dt.files;

  handleFiles(files);
}

Here, we retrieve the dataTransfer field from the event, then pull the file list out of it, passing that to handleFiles(). From this point on, handling the files is the same whether the user used the input element or drag and drop.

Example: Showing thumbnails of user-selected images

Let's say you're developing the next great photo-sharing web site, and want to use HTML5 to display thumbnail previews of images before the user actually uploads them. You can establish your input element or drop zone as discussed previously, and have them call a function such as the handleFiles() function below.

function handleFiles(files) {
  for (var i = 0; i < files.length; i++) {
    var file = files[i];
    var imageType = /image.*/;
    
    if (!file.type.match(imageType)) {
      continue;
    }
    
    var img = document.createElement("img");
    img.classList.add("obj");
    img.file = file;
    preview.appendChild(img);
    
    var reader = new FileReader();
    reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
    reader.readAsDataURL(file);
  }
}

Here our loop handling the user-selected files looks at each file's type attribute to see if it's an image file (by doing a regular expression match on the string "image.*"). For each file that is an image, we create a new img element. CSS can be used to establish any pretty borders, shadows, and to specify the size of the image, so that doesn't even need to be done here.

Each image has the CSS class obj added to it, to make them easy to find in the DOM tree. We also add a file attribute to each image specifying the File for the image; this will let us fetch the images for actually uploading later. Finally, we use Node.appendChild() to add the new thumbnail to the preview area of our document.

Then we establish the FileReader to handle actually asynchronously loading the image and attaching it to the img element. After creating the new FileReader object, we set up its onload function, then call readAsDataURL() to start the read operation in the background. When the entire contents of the image file are loaded, they are converted into a data: URL, which is passed to the onload callback. Our implementation of this routine simply sets the img element's src attribute to the loaded image, which results in the image appearing in the thumbnail on the user's screen.

Utiliser l'URL de l'objet

Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1) introduit ce support pour le DOM avec les méthodeswindow.URL.createObjectURL() et window.URL.revokeObjectURL(). Elles vous permettent de créer des chaînes d'URL simples qui peuvent être utilisés pour faire référence à toutes les données qui peuvent être visés à l'aide d'un objet DOM File, y compris les fichiers locaux sur l'ordinateur de l'utilisateur.

Lorsque vous avez un objet File que vous souhaitez référencer par son URL à partir de HTML, vous pouvez créer un objet URL comme ceci:

var objectURL = window.URL.createObjectURL(fileObj);

L'objet URL est une chaîne identifiant l'objet File. Chaque fois que vous appelez window.URL.createObjectURL(), un objet URL unique est créé, même si vous avez déjà créé un objet URL pour ce fichier. Chacun d'eux doit être libéré. Ils sont libérés automatiquement lorsque le document est déchargé, si votre page les utilise dynamiquement, vous devez les libérer explicitement en appelant window.URL.revokeObjectURL():

window.URL.revokeObjectURL(objectURL);

Exemple: Utilisation l'objet URL pour afficher des images

Cet exemple utilise des URL d'objets pour afficher les vignettes d'image. En outre, il affiche d'autres informations tel que leurs noms et leurs tailles. Vous pouvez voir l'exemple .

Le code HTML qui présente l'interface ressemble à ceci:

<input type="file" id="fileElem" multiple accept="image/*" style="display:none" onchange="handleFiles(this.files)">
<a href="#" id="fileSelect">Select some files</a> 
<div id="fileList">
  <p>No files selected!</p>
</div>

Ceci établit notre élément fichier <input>, ainsi qu'un lien qui appelle le sélecteur de fichiers, puisque nous gardons l'entrée de fichier caché pour empêcher que l'interface utilisateur moins que séduisante soit affiché. Ceci est expliqué dans la section Using hidden file input elements using the click() method, de même que la méthode qui appelle le sélecteur de fichiers.

Methode handleFiles():

window.URL = window.URL || window.webkitURL;

var fileSelect = document.getElementById("fileSelect"),
    fileElem = document.getElementById("fileElem"),
    fileList = document.getElementById("fileList");

fileSelect.addEventListener("click", function (e) {
  if (fileElem) {
    fileElem.click();
  }
  e.preventDefault(); // prevent navigation to "#"
}, false);

function handleFiles(files) {
  if (!files.length) {
    fileList.innerHTML = "<p>No files selected!</p>";
  } else {
    var list = document.createElement("ul");
    for (var i = 0; i < files.length; i++) {
      var li = document.createElement("li");
      list.appendChild(li);
      
      var img = document.createElement("img");
      img.src = window.URL.createObjectURL(files[i]);
      img.height = 60;
      img.onload = function(e) {
        window.URL.revokeObjectURL(this.src);
      }
      li.appendChild(img);
      
      var info = document.createElement("span");
      info.innerHTML = files[i].name + ": " + files[i].size + " bytes";
      li.appendChild(info);
    }
    fileList.appendChild(list);
  }
}

Cela commence par aller chercher l'URL de <div> avec l'ID fileList. Ceci est le bloc dans lequel nous allons insérer sur la liste de fichiers, y compris les vignettes.

Si l'objet FileList passé à handleFiles() est null, nous avons simplement mis un bloc innerHTML pour afficher "Aucun fichier sélectionné ! ". Sinon, nous commençons à construire notre liste de fichiers, comme suit:

  1. Une nouvelle liste d'Eléments à puces (<ul>) est créé.
  2. Le nouvel élément de liste est insérée dans le bloc <div> en appelant sa méthode element.appendChild().
  3. Pour chaque File dans le FileList représenté par files:
    1. Créer un nouvel élément de liste (<li>) et l'insérer dans la liste.
    2. Créer un nouvel élément image (<img>).
    3. Définissez la source de l'image comme nouvel objet URL représentant le fichier, en utilisant window.URL.createObjectURL() pour créer le blob URL.
    4. Régler la hauteur de l'image à 60 pixels.
    5. Configurer le gestionnaire d'événement de chargement de l'image pour libérer l'objet URL, car il n'est plus nécessaire une fois que l'image a été chargée. Cela se fait en appelant la méthode window.URL.revokeObjectURL(), en passant en parametre la chaîne objet URL img.src.
    6. Ajoutez le nouvel élément à la liste.

Example: Uploading a user-selected file

Another thing you might want to do is let the user upload the selected file or files (such as the images selected using the previous example) to a server. This can be done asynchronously very easily.

Creating the upload tasks

Continuing with the code that builds the thumbnails in the previous example, recall that every thumbnail image is in the CSS class obj, with the corresponding File attached in a file attribute. This lets us very easily select all the images the user has chosen for uploading using Document.querySelectorAll(), like this:

function sendFiles() {
  var imgs = document.querySelectorAll(".obj");
  
  for (var i = 0; i < imgs.length; i++) {
    new FileUpload(imgs[i], imgs[i].file);
  }
}

Line 2 creates an array, called imgs, of all the elements in the document with the CSS class obj. In our case, these will be all the image thumbnails. Once we have that list, it's trivial to go through the list, creating a new FileUpload instance for each. Each of these handles uploading the corresponding file.

Handling the upload process for a file

The FileUpload function accepts two inputs: an image element and a file from which to read the image data.

function FileUpload(img, file) {
  var reader = new FileReader();  
  this.ctrl = createThrobber(img);
  var xhr = new XMLHttpRequest();
  this.xhr = xhr;
  
  var self = this;
  this.xhr.upload.addEventListener("progress", function(e) {
        if (e.lengthComputable) {
          var percentage = Math.round((e.loaded * 100) / e.total);
          self.ctrl.update(percentage);
        }
      }, false);
  
  xhr.upload.addEventListener("load", function(e){
          self.ctrl.update(100);
          var canvas = self.ctrl.ctx.canvas;
          canvas.parentNode.removeChild(canvas);
      }, false);
  xhr.open("POST", "https://demos.hacks.mozilla.org/paul/demos/resources/webservices/devnull.php");
  xhr.overrideMimeType('text/plain; charset=x-user-defined-binary');
  reader.onload = function(evt) {
    xhr.sendAsBinary(evt.target.result);
  };
  reader.readAsBinaryString(file);
}

The FileUpload() function shown above creates a throbber, which is used to display progress information, then creates an XMLHttpRequest to handle uploading the data.

Before actually transferring the data, several preparatory steps are taken:

  1. The XMLHttpRequest's upload progress listener is set to update the throbber with new percentage information, so that as the upload progresses, the throbber will be updated based on the latest information.
  2. The XMLHttpRequest's upload load event handler is set to update the throbber with 100% as the progress information (to ensure the progress indicator actually reaches 100%, in case of granularity quirks during the process). It then removes the throbber, since it's no longer needed. This causes the throbber to disappear once the upload is complete.
  3. The request to upload the image file is opened by calling XMLHttpRequest's open() method to start generating a POST request.
  4. The MIME type for the upload is set by calling the XMLHttpRequest function overrideMimeType(). In this case, we're using a generic MIME type; you may or may not need to set the MIME type at all, depending on your use case.
  5. The FileReader object is used to convert the file to a binary string.
  6. Finally, when the content is loaded the XMLHttpRequest function sendAsBinary() is called to upload the file's content.

Handling the upload process for a file, asynchronously

<?php
if (isset($_FILES['myFile'])) {
    // Example:
    move_uploaded_file($_FILES['myFile']['tmp_name'], "uploads/" . $_FILES['myFile']['name']);
    exit;
}
?><!DOCTYPE html>
<html>
<head>
    <title>dnd binary upload</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script type="text/javascript">
        function sendFile(file) {
            var uri = "/index.php";
            var xhr = new XMLHttpRequest();
            var fd = new FormData();
            
            xhr.open("POST", uri, true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    // Handle response.
                    alert(xhr.responseText); // handle response.
                }
            };
            fd.append('myFile', file);
            // Initiate a multipart/form-data upload
            xhr.send(fd);
        }

        window.onload = function() {
            var dropzone = document.getElementById("dropzone");
            dropzone.ondragover = dropzone.ondragenter = function(event) {
                event.stopPropagation();
                event.preventDefault();
            }
    
            dropzone.ondrop = function(event) {
                event.stopPropagation();
                event.preventDefault();

                var filesArray = event.dataTransfer.files;
                for (var i=0; i<filesArray.length; i++) {
                    sendFile(filesArray[i]);
                }
            }
         }
    </script>
</head>
<body>
    <div>
        <div id="dropzone" style="margin:30px; width:500px; height:300px; border:1px dotted grey;">Drag & drop your file here...</div>
    </div>
</body>
</html>

Specifications

See also

Étiquettes et contributeurs liés au document

 Contributeurs à cette page : jmh, Mr21, vava, m2c, Goofy, LoeWzukW, jean_pierre
 Dernière mise à jour par : jmh,