關於前端上傳文件全面基礎掃盲貼(四) ----- FileReader

系列文章

關於前端上傳文件全面基礎掃盲貼(零)
關於前端上傳文件全面基礎掃盲貼(一) ----- XMLHttpRequest
關於前端上傳文件全面基礎掃盲貼(二) ----- File
關於前端上傳文件全面基礎掃盲貼(三) ----- FormData
關於前端上傳文件全面基礎掃盲貼(四) ----- FileReader
關於前端上傳文件全面基礎掃盲貼(五) ----- H5拖拽事件
關於前端上傳文件全面基礎掃盲貼(六) ----- 圖片上傳,旋轉,重繪,預覽等實戰(附DEMO)javascript

FileReader對象(知識點主要來源於關於FileReader API)

摘自上面來源,分析的挺好,我又無恥得搬下來了:css

使用 FileReader對象,web應用程序能夠異步的讀取存儲在用戶計算機上的文件(或者原始數據緩衝)內容,可使用 File對象或者 Blob對象來指定所要處理的文件或數據.其中File對象能夠是來自用戶在一個<input>元素上選擇文件後返回的 FileList對象,也能夠來自拖放操做生成的 DataTransfer對象,還能夠是來自在一個 HTMLCanvasElement上執行mozGetAsFile()方法後的返回結果.

在這裏做用就是當你上傳圖片以後,能夠直接從本地先讀取出原始數據,而後在頁面上展現出來,就是傳說中的預覽圖片功能,在上傳到後臺前就已經能先拿原始數據來使用了html

看看兼容性如何(舒適提示:下圖只表明支持程度,支持歸支持,不必定百分百支持,因此用到部分方法時不兼容時正常的)
圖片描述前端

建立一個FileReader對象:java

var reader = new FileReader();

事件處理程序:

事件 描述
onabort 當讀取操做被停止時調用
onerror 當讀取操做發生錯誤時調用
onload 當讀取操做成功完成時調用
onloadend 當讀取操做完成時調用,不論是成功仍是失敗.該處理程序在onload或者onerror以後調用
onloadstart 當讀取操做將要開始以前調用
onprogress 在讀取數據過程當中週期性調用
abort 停止該讀取操做.在返回時,readyState屬性的值爲DONE.當該FileReader對象沒有在進行讀取操做時(也就是readyState屬性的值不爲LOADING時),調用abort()方法會拋出異常DOM_FILE_ABORT_ERR

下面方法會開始讀取指定的Blob對象或File對象中的內容. 當讀取操做完成時,readyState屬性的值會成爲DONE,若是設置了onloadend事件處理程序,則調用之.區別在於:web

屬性 描述
readAsArrayBuffer result屬性中將包含一個ArrayBuffer對象以表示所讀取文件的內容
readAsBinaryString result屬性中將包含所讀取文件的原始二進制數據
readAsDataURL result屬性中將包含一個data: URL格式的字符串以表示所讀取文件的內容.(這個就是實現咱們預覽的重要方法了!!!!!)
readAsText result屬性中將包含一個字符串以表示所讀取的文件內容

介紹到這裏就差很少了,接下來看看怎麼實現不提交後臺實現預覽圖片,這裏只展現這部分功能先segmentfault

示例

<!doctype html>
<html>

  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
    <title></title>
    <script type="text/javascript">
      var oFReader = new FileReader();

      oFReader.onload = function (oFREvent) {
        document
          .getElementById("uploadPreview")
          .src = oFREvent.target.result;
      };

      function loadImageFile() {
        if (document.getElementById("uploadImage").files.length === 0) 
          return;
        var oFile = document
          .getElementById("uploadImage")
          .files[0];
        oFReader.readAsDataURL(oFile);
      }
    </script>
  </head>

  <body>
    <form name="uploadForm">
      <img id="uploadPreview"/>
      <input id="uploadImage" type="file" name="myPhoto" onchange="loadImageFile();"/>
    </form>
  </body>

</html>

你看,其實很簡單,沒什麼複雜代碼,只是須要的範圍比較廣,爲了一個上傳圖片已經摺騰了多少知識點了,還沒完呢...o(一︿一+)o瀏覽器

迴歸正題,說說幾個要點,首先看看代碼的
document.getElementById("uploadImage")出現了好幾回了,是否是好礙眼?是否是好想優化?是否是想爲何不把他放到一個變量存起來算了?
不行的,由於當你存一個變量以後再上傳文件,你就找不到FileReader對象了,詳情能夠參考一下我以前寫的關於Javascript基本類型和引用類型小知識app

而後oFReader.onload裏面的oFREvent就是你可以拿到的數據了,裏面大概長這樣子的,看的眼花繚亂,大家能夠慢慢挖掘異步

圖片描述
其中:
readyState: 0-尚未加載任何數據.1-數據正在被加載.2-已完成所有的讀取請求.
result: 返回文件的內容。只有在讀取操做完成後,此屬性纔有效,返回的數據的格式取決因而使用哪一種讀取方法來執行讀取操做的。

中間插播一則消息吧,圖中可看到一個result屬性的地址,那是一個base64 編碼.就是能夠將一副圖片數據編碼成一串字符串,使用該字符串代替圖像地址。
咱們所看到的網頁上的每個圖片,都是須要消耗一個 http 請求下載而來的,後面所以誕生的精靈圖就是基於這個問題纔出來,不過侷限性比較大,很難適用到全部項目
詳情能夠參考一下【前端攻略】:玩轉圖片Base64編碼

另外就是兼容問題,由於懶得一個個去驗證,就沒寫上去,不過查過資料放下來給大家,可能有用到,詳情能夠參考一下
對於 Chrome、Firefox、IE10 使用 FileReader 來實現。
對於 IE6~9 使用濾鏡 filter:progid:DXImageTransform.Microsoft.AlphaImageLoader 來實現。

<!doctype html>
<html>

  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
    <title></title>
    <script type="text/javascript">
      var loadImageFile = (function () {
        if (window.FileReader) {
          var oPreviewImg = null,
            oFReader = new window.FileReader(),
            rFilter = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i;

          oFReader.onload = function (oFREvent) {
            if (!oPreviewImg) {
              var newPreview = document.getElementById("imagePreview");
              oPreviewImg = new Image();
              newPreview.appendChild(oPreviewImg);
            }
            oPreviewImg.src = oFREvent.target.result;
          };

          return function () {
            var aFiles = document
              .getElementById("imageInput")
              .files;
            if (aFiles.length === 0) 
              return;
            if (!rFilter.test(aFiles[0].type)) {
              alert("You must select a valid image file!");
              return;
            }
            oFReader.readAsDataURL(aFiles[0]);
          }
        } else if (navigator.appName === "Microsoft Internet Explorer") {
          return function () {
            document
              .getElementById("imagePreview")
              .filters
              .item("DXImageTransform.Microsoft.AlphaImageLoader")
              .src = document
              .getElementById("imageInput")
              .value;
          }
        }
      })();
    </script>
    <style type="text/css">
      #imagePreview {
        filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale);
      }
    </style>
  </head>

  <body>
    <input id="imageInput" type="file" name="myPhoto" onchange="loadImageFile();"/>
    <div id="imagePreview"></div>
  </body>

</html>

沒有IE瀏覽器測試,因此不知道是否是有效,其實裏面看起來比我寫的那個複雜,實際上多了個檢驗格式:

rFilter = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i;

IE上兼容寫法:

document.getElementById("imagePreview").filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = document.getElementById("imageInput").value;

因此不要怕,若是我錯了記得提醒下我啊。

目前爲止其實已經該說的都差很少覆蓋到了吧,動手能力強的話已經能夠根據教程寫一個實例出來的了。我看狀況要不要加一個實戰代碼作系列結尾。

相關文章
相關標籤/搜索