瀏覽器—ArrayBuffer 對象,Blob 對象

1、ArrayBuffer 對象

ArrayBuffer 對象表示一段二進制數據,用來模擬內存裏面的數據。通過這個對象,JavaScript 可以讀寫二進制數據。這個對象可以看作內存數據的表達。

這個對象是 ES6 才寫入標準的,普通的網頁編程用不到它,爲了教程體系的完整,下面只提供一個簡略的介紹,詳細介紹請看《ES6 標準入門》裏面的章節。

瀏覽器原生提供ArrayBuffer()構造函數,用來生成實例。它接受一個整數作爲參數,表示這段二進制數據佔用多少個字節。

var buffer = new ArrayBuffer(8);

上面代碼中,實例對象buffer佔用8個字節。

ArrayBuffer 對象有實例屬性byteLength,表示當前實例佔用的內存長度(單位字節)。​​​​​​​

var buffer = new ArrayBuffer(8);buffer.byteLength // 8

ArrayBuffer 對象有實例方法slice(),用來複制一部分內存。它接受兩個整數參數,分別表示複製的開始位置(從0開始)和結束位置(複製時不包括結束位置),如果省略第二個參數,則表示一直複製到結束。​​​​​​​

var buf1 = new ArrayBuffer(8);var buf2 = buf1.slice(0);

上面代碼表示覆制原來的實例。

2、Blob 對象

2.1、簡介

Blob 對象表示一個二進制文件的數據內容,比如一個圖片文件的內容就可以通過 Blob 對象讀寫。它通常用來讀寫文件,它的名字是 Binary Large Object (二進制大型對象)的縮寫。它與 ArrayBuffer 的區別在於,它用於操作二進制文件,而 ArrayBuffer 用於操作內存。

瀏覽器原生提供Blob()構造函數,用來生成實例對象。​​​​​​​

new Blob(array [, options])

Blob構造函數接受兩個參數。第一個參數是數組,成員是字符串或二進制對象,表示新生成的Blob實例對象的內容;第二個參數是可選的,是一個配置對象,目前只有一個屬性type,它的值是一個字符串,表示數據的 MIME 類型,默認是空字符串。​​​​​​​

var htmlFragment = ['<a id="a"><b id="b">hey!</b></a>'];
var myBlob = new Blob(htmlFragment, {type : 'text/html'});

上面代碼中,實例對象myBlob包含的是字符串。生成實例的時候,數據類型指定爲text/html

下面是另一個例子,Blob 保存 JSON 數據。​​​​​​​

var obj = { hello: 'world' };
var blob = new Blob([ JSON.stringify(obj) ], {type : 'application/json'});

2.2、實例屬性和實例方法

Blob具有兩個實例屬性sizetype,分別返回數據的大小和類型。​​​​​​​

var htmlFragment = ['<a id="a"><b id="b">hey!</b></a>'];
var myBlob = new Blob(htmlFragment, {type : 'text/html'});

myBlob.size // 32
myBlob.type // "text/html"

Blob具有一個實例方法slice,用來拷貝原來的數據,返回的也是一個Blob實例。​​​​​​​

myBlob.slice(start, end, contentType)

slice方法有三個參數,都是可選的。它們依次是起始的字節位置(默認爲0)、結束的字節位置(默認爲size屬性的值,該位置本身將不包含在拷貝的數據之中)、新實例的數據類型(默認爲空字符串)。

2.3、獲取文件信息

文件選擇器<input type="file">用來讓用戶選取文件。出於安全考慮,瀏覽器不允許腳本自行設置這個控件的value屬性,即文件必須是用戶手動選取的,不能是腳本指定的。一旦用戶選好了文件,腳本就可以讀取這個文件。

文件選擇器返回一個 FileList 對象,該對象是一個類似數組的成員,每個成員都是一個 File 實例對象。File 實例對象是一個特殊的 Blob 實例,增加了namelastModifiedDate屬性。​​​​​​​

// HTML 代碼如下
// <input type="file" accept="image/*" multiple οnchange="fileinfo(this.files)"/>

function fileinfo(files) {
  for (var i = 0; i < files.length; i++) {
    var f = files[i];
    console.log(
      f.name, // 文件名,不含路徑
      f.size, // 文件大小,Blob 實例屬性
      f.type, // 文件類型,Blob 實例屬性
      f.lastModifiedDate // 文件的最後修改時間
    );
  }
}

除了文件選擇器,拖放 API 的dataTransfer.files返回的也是一個FileList 對象,它的成員因此也是 File 實例對象。

2.4、下載文件

AJAX 請求時,如果指定responseType屬性爲blob,下載下來的就是一個 Blob 對象。​​​​​​​

function getBlob(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', url);
  xhr.responseType = 'blob';
  xhr.onload = function () {
    callback(xhr.response);
  }
  xhr.send(null);
}

上面代碼中,xhr.response拿到的就是一個 Blob 對象。

2.5、生成 URL

瀏覽器允許使用URL.createObjectURL()方法,針對 Blob 對象生成一個臨時 URL,以便於某些 API 使用。這個 URL 以blob://開頭,表明對應一個 Blob 對象,協議頭後面是一個識別符,用來唯一對應內存裏面的 Blob 對象。這一點與data://URL(URL 包含實際數據)和file://URL(本地文件系統裏面的文件)都不一樣。​​​​​​​

var droptarget = document.getElementById('droptarget');

droptarget.ondrop = function (e) {
  var files = e.dataTransfer.files;
  for (var i = 0; i < files.length; i++) {
    var type = files[i].type;
    if (type.substring(0,6) !== 'image/')
      continue;
    var img = document.createElement('img');
    img.src = URL.createObjectURL(files[i]);
    img.onload = function () {
      this.width = 100;
      document.body.appendChild(this);
      URL.revokeObjectURL(this.src);
    }
  }
}

上面代碼通過爲拖放的圖片文件生成一個 URL,產生它們的縮略圖,從而使得用戶可以預覽選擇的文件。

瀏覽器處理 Blob URL 就跟普通的 URL 一樣,如果 Blob 對象不存在,返回404狀態碼;如果跨域請求,返回403狀態碼。Blob URL 只對 GET 請求有效,如果請求成功,返回200狀態碼。由於 Blob URL 就是普通 URL,因此可以下載。

2.6、讀取文件

取得 Blob 對象以後,可以通過FileReader對象,讀取 Blob 對象的內容,即文件內容。

FileReader 對象提供四個方法,處理 Blob 對象。Blob 對象作爲參數傳入這些方法,然後以指定的格式返回。

  • FileReader.readAsText():返回文本,需要指定文本編碼,默認爲 UTF-8。

  • FileReader.readAsArrayBuffer():返回 ArrayBuffer 對象。

  • FileReader.readAsDataURL():返回 Data URL。

  • FileReader.readAsBinaryString():返回原始的二進制字符串。

下面是FileReader.readAsText()方法的例子,用來讀取文本文件。​​​​​​​

// HTML 代碼如下
// <input type=’file' οnchange='readfile(this.files[0])'></input>
// <pre id='output'></pre>
function readfile(f) {
  var reader = new FileReader();
  reader.readAsText(f);
  reader.onload = function () {
    var text = reader.result;
    var out = document.getElementById('output');
    out.innerHTML = '';
    out.appendChild(document.createTextNode(text));
  }
  reader.onerror = function(e) {
    console.log('Error', e);
  };
}

上面代碼中,通過指定 FileReader 實例對象的onload監聽函數,在實例的result屬性上拿到文件內容。

下面是FileReader.readAsArrayBuffer()方法的例子,用於讀取二進制文件。​​​​​​​

// HTML 代碼如下
// <input type="file" οnchange="typefile(this.files[0])"></input>
function typefile(file) {
  // 文件開頭的四個字節,生成一個 Blob 對象
  var slice = file.slice(0, 4);
  var reader = new FileReader();
  // 讀取這四個字節
  reader.readAsArrayBuffer(slice);
  reader.onload = function (e) {
    var buffer = reader.result;
    // 將這四個字節的內容,視作一個32位整數
    var view = new DataView(buffer);
    var magic = view.getUint32(0, false);
    // 根據文件的前四個字節,判斷它的類型
    switch(magic) {
      case 0x89504E47: file.verified_type = 'image/png'; break;
      case 0x47494638: file.verified_type = 'image/gif'; break;
      case 0x25504446: file.verified_type = 'application/pdf'; break;
      case 0x504b0304: file.verified_type = 'application/zip'; break;
    }
    console.log(file.name, file.verified_type);
  };
}

 

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