title: Trying to upload multiple images using XHR 2 and PHP
body: <p>I'm having problems trying to upload files using the latest XHR 2 along with PHP.</p>
  
  <p>My code is as follows:</p>
  
  <p>HTML...</p>
  
  <pre><code>&lt;!doctype html&gt;
  &lt;html&gt;
      &lt;head&gt;
          &lt;title&gt;XHR Multiple File Upload&lt;/title&gt;
          &lt;link rel="stylesheet" type="text/css" href="upload.css"&gt;
      &lt;/head&gt;
      &lt;body&gt;
          &lt;input type="file" id="upload" multiple="true" accept="image/*"&gt;
          &lt;a href="#" id="upload-link"&gt;Click here to upload multiple files&lt;/a&gt;
          &lt;script src="upload.js"&gt;&lt;/script&gt;
      &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>JavaScript</p>
  
  <pre><code>var formdata, link, input, doc = document;
  
  if (window.FormData) {
      formdata = new FormData();
  }
  
  function init(){
      link = doc.getElementById("upload-link"),
      input = doc.getElementById("upload");
  
      link.addEventListener("click", process, false);
      input.addEventListener("change", displaySelectedFiles, false);
  }
  
  function process (e) {
      // If the input element is found then trigger the click event (which opens the file select dialog window)
      if (input) {
          input.click();
      }
  
      e.preventDefault();
  }
  
  function displaySelectedFiles(){
      // Once a user selects some files the 'change' event is triggered (along with this listener function)
      // We can access selected files via 'this.files' property object.
      var files = this.files,
          count = 0,
          len = files.length;
  
      while (count &lt; len) {
          createImage(files[count]);
          count++;
      }
  
      var confirm = doc.createElement("input");
          confirm.type = "submit";
          confirm.value = "Upload these files";
          confirm.id = "confirm";
  
      doc.body.appendChild(confirm);
  
      confirm.addEventListener("click", uploadFiles, false);
  }
  
  function createImage (file) {
      var element = doc.createElement("img");
          element.file = file;
          element.classList.add("thumbnail");
  
      // We store the file object as a property of the image (for use later)
      doc.body.appendChild(element);
  
      // The FileReader object lets web applications asynchronously read the contents of files
      var reader = new FileReader();  
  
      reader.onload = (function (img) { 
          return function (e) { 
              img.src = e.target.result;
          }; 
      })(element);
  
      reader.readAsDataURL(file);
  }
  
  function uploadFiles(){
      var reader = new FileReader(),
          imgs = doc.querySelectorAll(".thumbnail"),
          count = 0,
          len = imgs.length;
  
      while (count &lt; len) {
          // Once image file is read then we can 'send' the upload request
          reader.onload = function (e) {
              formdata.append("images[]", e.target.result);
          }
          reader.readAsDataURL(imgs[count].file);
          count++;
      }
  
      fileUpload();
  }
  
  function fileUpload(){
      var xhr = new XMLHttpRequest();
  
      function progressListener (e) {
          console.log("progressListener: ", e);
          if (e.lengthComputable) {
              var percentage = Math.round((e.loaded * 100) / e.total);
              console.log("Percentage loaded: ", percentage);
          }
      };
  
      function finishUpload (e) {
          console.log("Finished Percentage loaded: 100");
      };
  
      // XHR2 has an upload property with a 'progress' event
      xhr.upload.addEventListener("progress", progressListener, false);
  
      // XHR2 has an upload property with a 'load' event
      xhr.upload.addEventListener("load", finishUpload, false);
  
      // Begin uploading of file
      xhr.open("POST", "upload.php");
  
      xhr.onreadystatechange = function(){
          console.info("readyState: ", this.readyState);
          if (this.readyState == 4) {
              if ((this.status &gt;= 200 &amp;&amp; this.status &lt;= 200) || this.status == 304) {
                  if (this.responseText != "") {
                      console.warn(xhr.responseText);
                  }
              }
          }
      };
  
      xhr.send(formdata);
  }
  
  window.addEventListener("DOMContentLoaded", init, false);
  </code></pre>
  
  <p>PHP (I wasn't sure about the PHP code and found the below via this article <a href="http://net.tutsplus.com/tutorials/javascript-ajax/uploading-files-with-ajax/" rel="nofollow">http://net.tutsplus.com/tutorials/javascript-ajax/uploading-files-with-ajax/</a>)</p>
  
  <pre><code>foreach ($_FILES["images"]["error"] as $key =&gt; $error) {  
      if ($error == UPLOAD_ERR_OK) {  
          $name = $_FILES["images"]["name"][$key];
          move_uploaded_file( $_FILES["images"]["tmp_name"][$key], "uploaded-images/" . $_FILES['images']['name'][$key]);
      }
  }
  echo "Successfully Uploaded Images";
  </code></pre>
  
  <p>I get the success message back, but no files uploaded into the relevant folder. I think either the <code>formdata</code> isn't being stored properly via JavaScript OR it isn't being passed to the server properly for PHP to access (or it could be that the PHP code I grabbed from that article linked to above just doesn't work - as I'm not a PHP person I'm not 100% sure).</p>
  
  <p>Any help would be greatly appreciated.</p>
  
  <p>Kind regards,
  Mark</p>