File upload is one of the oldest operation of web design. After 20 years, it's still has no big change, difficult to handle, lack of interaction and poor user experience. Web developers have thought many methods to improve the experience of uploading file in web apps, they developed various plugins based on different JavaScript libraries. However, because of the difference among different web browsers, there is no common interface which makes these plugins work properly or easily on all web browsers.
HTML5 provides a series of new API which make some revolutionary changes to file upload. Britain programmer Remy Sharp summarized these new interfaces. We will disucss how to use HTML5 API to augment file upload process based on his summary. We will discuss following functions:
- iframe upload
- Ajax upload
- progress bar
- file preview
- Drag and drop upload
You can watch the demo by Remy Sharp here to get a basic understanding of all these. Although these APIs are not fully adopted, they are the trends. With these APIs, our codes can be very concise.
1. Traditional method
Let's start from the very basic. The traditional method of file upload is using the input file element.
 
    
    
  
All major web browsers support this method. In IE, it is :
Users select file first and then click the "Upload" button, the file will start uploading.
2. iframe upload
The traditional form upload is called synchronous uploading, i.e, after clicking "Upload" button, the webpage will be locked, users have to wait for the upload complete before they can continue to operate.
Is there any asynchronous upload method which can be used to upload file without reloading? Before HTML5, we can use iframe to achieve this. When users click the submit button, an iframe will be dynamically inserted. Here we use jQuery code to demo.
var form = $("#upload-form");
  form.on('submit',function() {
    // here inserting iframe element
  });
These are the codes of iframe insertion
  var seed = Math.floor(Math.random() * 1000);
  var id = "uploader-frame-" + seed;
  var callback = "uploader-cb-" + seed;
  var iframe = $('
  var url = form.attr('action');
  form.attr('target', id).append(iframe).attr('action', url + '?iframe=' + callback);
We should pay attention to the last line. First, it will add the target attribute to the form, which will points to the dynamically inserted iframe, this will make the server send output to the iframe window and the webpage will not be refreshed. Second, it adds a query element to the action url which defines the callback function, this can make the results in iframe window pass back to parent window.
upload.php should have following codes
We should define the callback function in the current webpage
  window[callback] = function(data){
    console.log('received callback:', data);
    iframe.remove(); //removing iframe
    form.removeAttr('target');
    form.attr('action', url);
    window[callback] = undefined; //removing callback
  };
3. Ajax upload
HTML5 proposes the second version of XMLHttpRequest object, now Ajax can reallly do asynchronous file upload, it will be mainstream.
We can put Ajax upload codes in the submit function
form.on('submit',function() {
    //Here insert Ajax code
  });
We will use FormData object which can construct name-values pairs
// Check whether supporting FormData
  if(window.FormData) { 
    var formData = new FormData();
    // create an upload form element
    formData.append('upload', document.getElementById('upload').files[0]);
    var xhr = new XMLHttpRequest();
    xhr.open('POST', $(this).attr('action'));
    // define callback function after uploading
    xhr.onload = function () {
      if (xhr.status === 200) {
        console.log('Upload success');
      } else {
        console.log('Upload failure');
      }
    };
    xhr.send(formData);
  }
4. Progress bar
XMLHttpRequest second version defines a progress property which can be used to create progress bar.
First, we can put a HTML progress element
0
then we have the callback function of progress event
xhr.upload.onprogress = function (event) {
    if (event.lengthComputable) {
      var complete = (event.loaded / event.total * 100 | 0);
      var progress = document.getElementById('uploadprogress');
      progress.value = progress.innerHTML = complete;
    }
  };
Note : progress event is not for xhr, but for xhr.upload, because we need to distinguish download and upload, download will also have a progress event.
5. File preview
If we upload pictures, we can use File API. We can build a panel for picure preview.
  // Check whether supporting FileReader object
  if (typeof FileReader != 'undefined') {
    var acceptedTypes = {
      'image/png': true,
      'image/jpeg': true,
      'image/gif': true
    };
    if (acceptedTypes[document.getElementById('upload').files[0].type] === true) {
      var reader = new FileReader();
      reader.onload = function (event) {
        var image = new Image();
        image.src = event.target.result;
        image.width = 100;
        document.body.appendChild(image);
      };
    reader.readAsDataURL(document.getElementById('upload').files[0]);
    }
  }
6. Drag and drop upload
At last, we can use HTML5's drag and drop feature.
First we put a container in the ppage which is to accept dropped file.
Set CSS
  #holder {
    border: 10px dashed #ccc;
    width: 300px;
    min-height: 300px;
    margin: 20px auto;
  }
  #holder.hover {
    border: 10px dashed #0c0;
  }
The drag and drop code, we need to define the dragover,dragend and drop events
// Check whether browser suports drag and drop
  if('draggable' in document.createElement('span')){
    var holder = document.getElementById('holder');
    holder.ondragover = function () { this.className = 'hover'; return false; };
    holder.ondragend = function () { this.className = ''; return false; };
    holder.ondrop = function (event) {
      event.preventDefault();
      this.className = '';
      var files = event.dataTransfer.files;
      // do something with files
    };
  }
The complete demo can be viewed here.
Original author : 阮一峰 Reference : http://www.ruanyifeng.com/blog/2012/08/file_upload.html