JS-前端使用Blob和File讀取文件

目錄

  • Blob及其屬性和方法
  • File
  • FileReader及其屬性和方法
  • URL及其屬性和方法

歷史上,JavaScript 無法處理二進制數據。如果一定要處理的話,只能使用 charCodeAt() 方法,一個個字節地從文字編碼轉成二進制數據,還有一種辦法是將二進制數據轉成 Base64 編碼,再進行處理。這兩種方法不僅速度慢,而且容易出錯。ECMAScript 5 引入了 Blob 對象,允許直接操作二進制數據。

Blob 對象是一個代表二進制數據的基本對象,在它的基礎上,又衍生出一系列相關的API,用來操作文件。

  • File對象:負責處理那些以文件形式存在的二進制數據,也就是操作本地文件;
  • FileList對象:File對象的網頁表單接口;
  • FileReader對象:負責將二進制數據讀入內存內容;
  • URL對象:用於對二進制數據生成URL

Blob

Blob (Binary Large Object) 對象代表了一段二進制數據,提供了一系列操作接口。其他操作二進制數據的API(比如 File 對象),都是建立在 Blob 對象基礎上的,繼承了它的屬性和方法。

創建 Blob 類型的對象

生成 Blob 對象有兩種方法:一種是使用 Blob 構造函數,另一種是對現有的 Blob 對象使用 slice 方法切出一部分。

1. new Blob()

Blob 構造函數,接受兩個參數。第一個參數是一個包含實際數據的數組,這個數組中的元素可以爲 DOMString ,或者 ArrayBuffer ,第二個參數是數據的類型,這兩個參數都不是必需的。

var domstring = '<div>Hello world</div>';
var blob1 = new Blob([domstring], {type: 'text/html'});

var buffer = new ArrayBuffer(8);
var blob2 = new Blob([buffer], {type: 'text/plain'});

2. blob.slice()

此方法返回一個新的 Blob 對象,包含了原 Blob 對象中指定範圍內的數據

Blob.slice(start:number, end:number, contentType:string)。start:開始索引,默認爲0;end:截取結束索引(不包括end);contentType:新Blob的MIME類型,默認爲空字符串

Blob 對象的屬性

  • Blob.size: Blob 對象中所包含數據的大小(字節)。該屬性爲只讀;
  • Blob.type: 一個字符串,表明該 Blob 對象所包含數據的 MIME 類型。如果類型未知,則該值爲空字符串。該屬性爲只讀

Blob 應用實例

下面是一個使用XMLHttpRequest對象,將大文件分割上傳的例子。

function upload(blobOrFile) {
  let xhr = new XMLHttpRequest();
  xhr.open('post', '/server', true);
  xhr.onload = function(e) {};
  xhr.send(blobOrFile);
}

document.querySelctor('input[type="file"]').addEventListener('change', function() {
  let blob = this.files[0];
  const BYTES_PER_CHUNK = 1024 * 1024; // 1MB chunk size
  const SIZE = blob.size;
  let start = 0;
  let end = BYTES_PER_CHUNK;
  while(start < end) {
    upload(blob.slice(start, end));
    start = end;
    end = start + BYTES_PER_CHUNK;
  }
}, false);

File

File 接口提供有關文件的信息,並允許網頁中的 JavaScript 訪問其內容。

File 對象可以用來獲取某個文件的信息,還可以用來讀取這個文件的內容。通常情況下, File 對象是來自用戶在一個 <input> 元素上選擇文件後返回的 FileList 對象,也可以是來自由拖放操作生成的 DataTransfer 對象。

用戶在選擇一個或者多個文件後,可以通過 File API訪問這些File 對象,這些對象被包含在一個 FileList 對象中。所有 typefileinput 都有一個 files 屬性,通過 Element.files 可以返回 FileList 對象。

<body>
    <input type="file" id="fileInput" name="file" multiple="multiple" accept="image/*">
    <script>
        var fileInput = document.querySelector("#fileInput");
        fileInput.addEventListener("change", function (event) {
          // 文件列表對象
          var fileList = this.files;
          // 獲取第一個文件
          var file = fileInput.files[0];
          // 文件名
          var filename = file.name;
          // 文件大小
          var filesize = file.size;
          //文件的 MIME 類型,如果分辨不出類型,則爲空字符串,該屬性只讀
          var type = file.type; 
          // 文件的上次修改時間,格式爲時間戳
          var lastModified = file.lastModified;
          // 文件的上次修改時間,格式爲 Date 對象實例
          var lastModifiedDate = file.lastModifiedDate;
        }, false);

        console.log(fileList);
        // 上傳了兩個文件,FileList {0: File, 1: File, length: 2}
    </script>
</body>

File 對象的屬性:

  • name:文件名,該屬性只讀。
  • size:文件大小,單位爲字節,該屬性只讀。
  • type:文件的 MIME 類型,如果分辨不出類型,則爲空字符串,該屬性只讀。
  • lastModified:文件的上次修改時間,格式爲時間戳。
  • lastModifiedDate:文件的上次修改時間,格式爲 Date 對象實例

File 對象的方法:

File 接口沒有定義任何方法,但是它從 Blob 接口繼承了以下方法:

Blob.slice([start[, end[, contentType]]])

返回一個新的 Blob 對象,它包含有源 Blob 對象中指定範圍內的數據。

FileReader

我們知道 Blob 對象只是二進制數據的容器,本身並不能操作二進制,FileReader 對象就是專門操作二進制數據的,FileReader 主要用於將文件內容讀入內存,通過一系列異步接口,可以在主線程中訪問本地文件。

構造函數

var reader = new FileReader();

屬性

  • FileReader.error:表示在讀取文件時發生的錯誤;
  • FileReader.readyState:0-還沒有加載任何數據, 1-數據正在被加載, 2-已完成全部的讀取請求;
  • FileReader.result:文件的內容。該屬性僅在讀取操作完成後纔有效,數據的格式取決於使用哪個方法來啓動讀取操作。

事件

  • FileReader.onabort:處理 abort 事件。該事件在讀取操作被中斷時觸發;
  • FileReader.onerror:處理 error 事件。該事件在讀取操作發生錯誤時觸發;
  • FileReader.onload:處理 load 事件。該事件在讀取操作完成時觸發;
  • FileReader.onloadstart:處理 loadstart 事件。該事件在讀取操作開始時觸發;
  • FileReader.onloadend:處理 loadend 事件。該事件在讀取操作結束時(要麼成功,要麼失敗)觸發;
  • FileReader.onprogress:處理 progress 事件。該事件在讀取 Blob 時觸發

方法

  • FileReader.abort():中止讀取操作。在返回時,readyState 屬性爲DONE;
  • FileReader.readAsArrayBuffer():開始讀取指定的 Blob 中的內容, 一旦完成, result 屬性中保存的將是被讀取文件的 ArrayBuffer 數據對象;
  • FileReader.readAsBinaryString():開始讀取指定的 Blob 中的內容。一旦完成,result 屬性中將包含所讀取文件的原始二進制數據, 該方法將文件讀取爲二進制字符串,通常我們將它傳送到後端,後端可以通過這段字符串存儲文件;
  • FileReader.readAsDataURL():開始讀取指定的 Blob 中的內容。一旦完成,result 屬性中將包含一個 data: URL 格式的字符串以表示所讀取文件的內容;
  • FileReader.readAsText():開始讀取指定的 Blob 中的內容。一旦完成,result 屬性中將包含一個字符串以表示所讀取的文件內容, 該方法有兩個參數,其中第二個參數是文本的編碼方式,默認值爲 UTF-8。這個方法非常容易理解,將文件以文本方式讀取,讀取的結果即是這個文本文件中的內容。

實際應用

上傳圖片後直接進行預覽,而不用先經過後臺。

var input  = document.getElementById("file"); //input file
input.onchange = function(){
    var file = this.files[0];
    if(!!file){
        var reader = new FileReader();
        // 將圖片轉成DataURL格式
        reader.readAsDataURL(file);
        reader.onload = function(){
            //讀取完畢後輸出結果
           document.getElementById("file_img").src = reader.result //顯示上傳的圖片
           console.log(reader.result);
        }
    }
}

URL

URL.createObjectURL(blob)

//blob參數是一個File對象或者Blob對象.
var objecturl =  window.URL.createObjectURL(blob);

上面的代碼會對二進制數據生成一個 URL ,這個 URL 可以放置於任何通常可以放置 URL 的地方,比如 img 標籤的 src 屬性。需要注意的是,即使是同樣的二進制數據,每調用一次 URL.createObjectURL 方法,就會得到一個不一樣的 URL

這個 URL 的存在時間,等同於網頁的存在時間,一旦網頁刷新或卸載,這個 URL 就失效。(File 和 Blob 又何嘗不是這樣呢)除此之外,也可以手動調用 URL.revokeObjectURL 方法,使 URL 失效。

URL.revokeObjectURL(objectURL);

當不再需要這些 URL 對象時,每個對象必須通過調用 URL.revokeObjectURL() 方法來釋放。瀏覽器會在文檔退出的時候自動釋放它們,但是爲了獲得最佳性能和內存使用狀況,你應該在安全的時機主動釋放掉它們。

實際應用

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>文件上傳</title>
    <script src="./lib/jquery.js"></script>
    <style type="text/css">
        #file{
            display: block;
            width: 400px;
            height: 300px;
            opacity:0;
            margin: -300px 0 0 0;            
        }
        #preview{
            display: block;
            width: 400px;
            height: 300px;
        }
    </style>
</head>
<body>
    <img id="preview" src="" alt="點擊上傳圖片"/>
    <input type="file" id="file" />
</body>
</html>
<script type="text/javascript">
  $('#file').on('change', function(){
    //獲取文件列表對象
    var fileList = $('#file')[0].files;
    //創建文件流獲取文件地址
    var src = window.URL.createObjectURL(fileList[0]);     
    //設置圖片路徑  
    $("#preview").attr("src", src);
    $("#preview").load(function() {
      window.URL.revokeObjectURL(src);
    });
 });
</script>

參考資料

Blob - Web API 接口參考 | MDN

Blob,FileReader全面解析

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章