JavaScript ArrayBuffer 對(duì)象,Blog 對(duì)象

2023-03-20 15:44 更新

ArrayBuffer 對(duì)象 

ArrayBuffer 對(duì)象表示一段二進(jìn)制數(shù)據(jù),用來(lái)模擬內(nèi)存里面的數(shù)據(jù)。通過(guò)這個(gè)對(duì)象,JavaScript 可以讀寫二進(jìn)制數(shù)據(jù)。這個(gè)對(duì)象可以看作內(nèi)存數(shù)據(jù)的表達(dá)。

這個(gè)對(duì)象是 ES6 才寫入標(biāo)準(zhǔn)的,普通的網(wǎng)頁(yè)編程用不到它,為了教程體系的完整,下面只提供一個(gè)簡(jiǎn)略的介紹,詳細(xì)介紹請(qǐng)看《ES6 標(biāo)準(zhǔn)入門》里面的章節(jié)。

瀏覽器原生提供ArrayBuffer()構(gòu)造函數(shù),用來(lái)生成實(shí)例。它接受一個(gè)整數(shù)作為參數(shù),表示這段二進(jìn)制數(shù)據(jù)占用多少個(gè)字節(jié)。

var buffer = new ArrayBuffer(8);

上面代碼中,實(shí)例對(duì)象buffer占用8個(gè)字節(jié)。

ArrayBuffer 對(duì)象有實(shí)例屬性byteLength,表示當(dāng)前實(shí)例占用的內(nèi)存長(zhǎng)度(單位字節(jié))。

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

ArrayBuffer 對(duì)象有實(shí)例方法slice(),用來(lái)復(fù)制一部分內(nèi)存。它接受兩個(gè)整數(shù)參數(shù),分別表示復(fù)制的開(kāi)始位置(從0開(kāi)始)和結(jié)束位置(復(fù)制時(shí)不包括結(jié)束位置),如果省略第二個(gè)參數(shù),則表示一直復(fù)制到結(jié)束。

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

上面代碼表示復(fù)制原來(lái)的實(shí)例。

Blob 對(duì)象 

簡(jiǎn)介 

Blob 對(duì)象表示一個(gè)二進(jìn)制文件的數(shù)據(jù)內(nèi)容,比如一個(gè)圖片文件的內(nèi)容就可以通過(guò) Blob 對(duì)象讀寫。它通常用來(lái)讀寫文件,它的名字是 Binary Large Object (二進(jìn)制大型對(duì)象)的縮寫。它與 ArrayBuffer 的區(qū)別在于,它用于操作二進(jìn)制文件,而 ArrayBuffer 用于操作內(nèi)存。

瀏覽器原生提供Blob()構(gòu)造函數(shù),用來(lái)生成實(shí)例對(duì)象。

new Blob(array [, options])

Blob構(gòu)造函數(shù)接受兩個(gè)參數(shù)。第一個(gè)參數(shù)是數(shù)組,成員是字符串或二進(jìn)制對(duì)象,表示新生成的Blob實(shí)例對(duì)象的內(nèi)容;第二個(gè)參數(shù)是可選的,是一個(gè)配置對(duì)象,目前只有一個(gè)屬性type,它的值是一個(gè)字符串,表示數(shù)據(jù)的 MIME 類型,默認(rèn)是空字符串。

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

上面代碼中,實(shí)例對(duì)象myBlob包含的是字符串。生成實(shí)例的時(shí)候,數(shù)據(jù)類型指定為text/html。

下面是另一個(gè)例子,Blob 保存 JSON 數(shù)據(jù)。

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

實(shí)例屬性和實(shí)例方法 

Blob具有兩個(gè)實(shí)例屬性sizetype,分別返回?cái)?shù)據(jù)的大小和類型。

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具有一個(gè)實(shí)例方法slice,用來(lái)拷貝原來(lái)的數(shù)據(jù),返回的也是一個(gè)Blob實(shí)例。

myBlob.slice(start, end, contentType)

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

獲取文件信息 

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

文件選擇器返回一個(gè) FileList 對(duì)象,該對(duì)象是一個(gè)類似數(shù)組的成員,每個(gè)成員都是一個(gè) File 實(shí)例對(duì)象。File 實(shí)例對(duì)象是一個(gè)特殊的 Blob 實(shí)例,增加了namelastModifiedDate屬性。

// HTML 代碼如下
// <input type="file" accept="image/*" multiple onchange="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 實(shí)例屬性
      f.type, // 文件類型,Blob 實(shí)例屬性
      f.lastModifiedDate // 文件的最后修改時(shí)間
    );
  }
}

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

下載文件 

AJAX 請(qǐng)求時(shí),如果指定responseType屬性為blob,下載下來(lái)的就是一個(gè) Blob 對(duì)象。

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拿到的就是一個(gè) Blob 對(duì)象。

生成 URL 

瀏覽器允許使用URL.createObjectURL()方法,針對(duì) Blob 對(duì)象生成一個(gè)臨時(shí) URL,以便于某些 API 使用。這個(gè) URL 以blob://開(kāi)頭,表明對(duì)應(yīng)一個(gè) Blob 對(duì)象,協(xié)議頭后面是一個(gè)識(shí)別符,用來(lái)唯一對(duì)應(yīng)內(nèi)存里面的 Blob 對(duì)象。這一點(diǎn)與data://URL(URL 包含實(shí)際數(shù)據(jù))和file://URL(本地文件系統(tǒng)里面的文件)都不一樣。

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);
    }
  }
}

上面代碼通過(guò)為拖放的圖片文件生成一個(gè) URL,產(chǎn)生它們的縮略圖,從而使得用戶可以預(yù)覽選擇的文件。

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

讀取文件 

取得 Blob 對(duì)象以后,可以通過(guò)FileReader對(duì)象,讀取 Blob 對(duì)象的內(nèi)容,即文件內(nèi)容。

FileReader 對(duì)象提供四個(gè)方法,處理 Blob 對(duì)象。Blob 對(duì)象作為參數(shù)傳入這些方法,然后以指定的格式返回。

  • FileReader.readAsText():返回文本,需要指定文本編碼,默認(rèn)為 UTF-8。
  • FileReader.readAsArrayBuffer():返回 ArrayBuffer 對(duì)象。
  • FileReader.readAsDataURL():返回 Data URL。
  • FileReader.readAsBinaryString():返回原始的二進(jìn)制字符串。

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

// HTML 代碼如下
// <input type="file" onchange="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);
  };
}

上面代碼中,通過(guò)指定 FileReader 實(shí)例對(duì)象的onload監(jiān)聽(tīng)函數(shù),在實(shí)例的result屬性上拿到文件內(nèi)容。

下面是FileReader.readAsArrayBuffer()方法的例子,用于讀取二進(jìn)制文件。

// HTML 代碼如下
// <input type="file" onchange="typefile(this.files[0])"></input>
function typefile(file) {
  // 文件開(kāi)頭的四個(gè)字節(jié),生成一個(gè) Blob 對(duì)象
  var slice = file.slice(0, 4);
  var reader = new FileReader();
  // 讀取這四個(gè)字節(jié)
  reader.readAsArrayBuffer(slice);
  reader.onload = function (e) {
    var buffer = reader.result;
    // 將這四個(gè)字節(jié)的內(nèi)容,視作一個(gè)32位整數(shù)
    var view = new DataView(buffer);
    var magic = view.getUint32(0, false);
    // 根據(jù)文件的前四個(gè)字節(jié),判斷它的類型
    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);
  };
}


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)