初識html5 File API實現帶有進度提示的文件上傳

Html5終於解決了上傳文件的同時顯示文件上傳進度的老問題。如今大部分的網站用Flash去實現這一功能,還有一些網站繼續採用Html <form>with enctype=multipart/form-data,可是須要修改服務器端可用才能顯示給用戶文件上傳的進度。本質上你須要作的工做是在服務器端接收一個文件時,你發送給它一個字節流,因此你須要知道你已經接收到多少字節並以某種方式傳達這些信息給客戶端瀏覽器,在這個過程一直在不斷的進行文件的上傳。這種方式運行的很是好,不像Flash上傳那這樣充滿了問題(特別是處理大文件上傳的時候),然而這種方法是至關複雜的而且聽起來不容易理解,由於你本質上是接管了整個服務器端的處理(獲取字節流的時候)同時包括了在服務器端實現multipart/form-data協議,伴隨一系列的其餘事情。javascript

使用Html5 上傳文件

XMLHttpRequest 在Html5 規範中已經有全新的變化,規定了XMLHttpRequest Level 2規範(目前最新版本)包含下列新的特性:html

  1. 處理字節流,例如做爲上傳或者下載的File,Blob,FormData對象
  2. 上傳或者下載中的進度事件
  3. 跨站點請求
  4. 容許建立匿名請求
  5. 能夠設置請求超時

在這篇文章中咱們將可以更清楚的看到#1和#2兩個特性。一般,上傳文件用XMLHttpRequest而且提供上傳進度信息給最終的用戶,須要注意的是這種方式解決了不須要服務器端作任何改變,至少是目前處理multipart/form-data協議。因此服務器端的處理邏輯保留不變,這使得開發者適應這種技術至關容易。java

enter image description here 圖1:文件上傳畫面-準備上傳 enter image description here 圖2:顯示上傳完成畫面瀏覽器

注意:上面的圖片中,信息提示區域是提供給用戶的:服務器

  1. 當前選中文件的信息
    • 文件名
    • 文件大小
    • 文件類型
  2. 上傳完成多少的百分比進度條
  3. 上傳速度或者上傳帶寬
  4. 距離上傳完成大概還有多長時間
  5. 已上傳文件大小
  6. 服務器端的響應

上面第6項或許看起來不重要,但事實上是至關重要的。由於咱們用XMLHttpRequest,上傳發生在後臺,頁面沒有發生跳轉等任何變化,因此對於你用它處理其餘一些事情來講是一個很是好的特性。app

Html5 Progress Event

對於Html5 Progress Events規範,Html5 Progess Events提供了下列與本次討論相關的信息post

  1. total - 總的字節數
  2. loaded - 到目前爲止上傳的字節數
  3. lengthComputable - 可計算的已上傳字節

請注意到咱們須要用兩個信息去計算要顯示給用戶的其餘全部信息。要計算出來其餘的信息經過上面咱們獲得信息是至關容易的,可是那須要一些額外的代碼而且建立一個定時器。網站

Html5 Progress Event 應該是什麼

考慮到有一部分人想更好的提供給用戶全部的信息,因此Html5 Progress Event應該更好的知足須要,由於它給瀏覽器供應商提供這些額外信息是至關簡單的,因此建議progress event應該修改爲以下:spa

  1. total - 總的字節數
  2. loaded - 到目前爲止上傳的字節數
  3. lengthComputable - 可計算的已上傳字節
  4. transferSpeed long類型
  5. timeRemaining JavaScript 日期對象

Html5 上傳 用XMLHttpRequest

瀏覽器支持狀況

支持這一特性的瀏覽器最低版本code

  1. Firefox 4.0 beta 6
  2. Chrome 6
  3. Safari 5.02

IE 9 Beta and Opera 10.62 不支持這一特性

簡單的示例

下面是一個完整的Html頁面包含了實現文件上傳並帶有進度提示的JavaScript代碼,只是實現了基本的功能,感興趣的能夠本身作擴展。 須要吧上傳接口修改爲本身服務的。 

 

<!DOCTYPE html>
<html>
<head>
    <title>Upload Files using XMLHttpRequest - Minimal</title>
    <script type="text/javascript">
      function fileSelected() {
        var file = document.getElementById('fileToUpload').files[0];
        if (file) {
          var fileSize = 0;
          if (file.size > 1024 * 1024)
            fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB';
          else
            fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB';
          document.getElementById('fileName').innerHTML = 'Name: ' + file.name;
          document.getElementById('fileSize').innerHTML = 'Size: ' + fileSize;
          document.getElementById('fileType').innerHTML = 'Type: ' + file.type;
        }
      }
      function uploadFile() {
        var fd = new FormData();
        fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]);
        var xhr = new XMLHttpRequest();
        xhr.upload.addEventListener("progress", uploadProgress, false);
        xhr.addEventListener("load", uploadComplete, false);
        xhr.addEventListener("error", uploadFailed, false);
        xhr.addEventListener("abort", uploadCanceled, false);
        xhr.open("POST", "upload.do");//修改爲本身的接口
        xhr.send(fd);
      }
      function uploadProgress(evt) {
        if (evt.lengthComputable) {
          var percentComplete = Math.round(evt.loaded * 100 / evt.total);
          document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';
        }
        else {
          document.getElementById('progressNumber').innerHTML = 'unable to compute';
        }
      }
      function uploadComplete(evt) {
        /* 服務器端返回響應時候觸發event事件*/
        alert(evt.target.responseText);
      }
      function uploadFailed(evt) {
        alert("There was an error attempting to upload the file.");
      }
      function uploadCanceled(evt) {
        alert("The upload has been canceled by the user or the browser dropped the connection.");
      }
    </script>
</head>
<body>
  <form id="form1" enctype="multipart/form-data" method="post" action="Upload.aspx">
    <div class="row">
      <label for="fileToUpload">Select a File to Upload</label><br />
      <input type="file" name="fileToUpload" id="fileToUpload" onchange="fileSelected();"/>
    </div>
    <div id="fileName"></div>
    <div id="fileSize"></div>
    <div id="fileType"></div>
    <div class="row">
      <input type="button" onclick="uploadFile()" value="Upload" />
    </div>
    <div id="progressNumber"></div>
  </form>
</body>
</html>
相關文章
相關標籤/搜索