# ArrayBuffer 對象,Blob 對象
## ArrayBuffer 對象
ArrayBuffer 對象表示一段二進制數據,用來模擬內存里面的數據。通過這個對象,JavaScript 可以讀寫二進制數據。這個對象可以看作內存數據的表達。
這個對象是 ES6 才寫入標準的,普通的網頁編程用不到它,為了教程體系的完整,下面只提供一個簡略的介紹,詳細介紹請看《ES6 標準入門》里面的章節。
瀏覽器原生提供`ArrayBuffer()`構造函數,用來生成實例。它接受一個整數作為參數,表示這段二進制數據占用多少個字節。
```javascript
var buffer = new ArrayBuffer(8);
```
上面代碼中,實例對象`buffer`占用8個字節。
ArrayBuffer 對象有實例屬性`byteLength`,表示當前實例占用的內存長度(單位字節)。
```javascript
var buffer = new ArrayBuffer(8);
buffer.byteLength // 8
```
ArrayBuffer 對象有實例方法`slice()`,用來復制一部分內存。它接受兩個整數參數,分別表示復制的開始位置(從0開始)和結束位置(復制時不包括結束位置),如果省略第二個參數,則表示一直復制到結束。
```javascript
var buf1 = new ArrayBuffer(8);
var buf2 = buf1.slice(0);
```
上面代碼表示復制原來的實例。
## Blob 對象
### 簡介
Blob 對象表示一個二進制文件的數據內容,比如一個圖片文件的內容就可以通過 Blob 對象讀寫。它通常用來讀寫文件,它的名字是 Binary Large Object (二進制大型對象)的縮寫。它與 ArrayBuffer 的區別在于,它用于操作二進制文件,而 ArrayBuffer 用于操作內存。
瀏覽器原生提供`Blob()`構造函數,用來生成實例對象。
```javascript
new Blob(array [, options])
```
`Blob`構造函數接受兩個參數。第一個參數是數組,成員是字符串或二進制對象,表示新生成的`Blob`實例對象的內容;第二個參數是可選的,是一個配置對象,目前只有一個屬性`type`,它的值是一個字符串,表示數據的 MIME 類型,默認是空字符串。
```javascript
var htmlFragment = ['<a id="a"><b id="b">hey!</b></a>'];
var myBlob = new Blob(htmlFragment, {type : 'text/html'});
```
上面代碼中,實例對象`myBlob`包含的是字符串。生成實例的時候,數據類型指定為`text/html`。
下面是另一個例子,Blob 保存 JSON 數據。
```javascript
var obj = { hello: 'world' };
var blob = new Blob([ JSON.stringify(obj) ], {type : 'application/json'});
```
### 實例屬性和實例方法
`Blob`具有兩個實例屬性`size`和`type`,分別返回數據的大小和類型。
```javascript
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`實例。
```javascript
myBlob.slice(start, end, contentType)
```
`slice`方法有三個參數,都是可選的。它們依次是起始的字節位置(默認為0)、結束的字節位置(默認為`size`屬性的值,該位置本身將不包含在拷貝的數據之中)、新實例的數據類型(默認為空字符串)。
### 獲取文件信息
文件選擇器`<input type="file">`用來讓用戶選取文件。出于安全考慮,瀏覽器不允許腳本自行設置這個控件的`value`屬性,即文件必須是用戶手動選取的,不能是腳本指定的。一旦用戶選好了文件,腳本就可以讀取這個文件。
文件選擇器返回一個 FileList 對象,該對象是一個類似數組的成員,每個成員都是一個 File 實例對象。File 實例對象是一個特殊的 Blob 實例,增加了`name`和`lastModifiedDate`屬性。
```javascript
// 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 實例屬性
f.type, // 文件類型,Blob 實例屬性
f.lastModifiedDate // 文件的最后修改時間
);
}
}
```
除了文件選擇器,拖放 API 的`dataTransfer.files`返回的也是一個FileList 對象,它的成員因此也是 File 實例對象。
### 下載文件
AJAX 請求時,如果指定`responseType`屬性為`blob`,下載下來的就是一個 Blob 對象。
```javascript
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 對象。
### 生成 URL
瀏覽器允許使用`URL.createObjectURL()`方法,針對 Blob 對象生成一個臨時 URL,以便于某些 API 使用。這個 URL 以`blob://`開頭,表明對應一個 Blob 對象,協議頭后面是一個識別符,用來唯一對應內存里面的 Blob 對象。這一點與`data://URL`(URL 包含實際數據)和`file://URL`(本地文件系統里面的文件)都不一樣。
```javascript
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,因此可以下載。
### 讀取文件
取得 Blob 對象以后,可以通過`FileReader`對象,讀取 Blob 對象的內容,即文件內容。
FileReader 對象提供四個方法,處理 Blob 對象。Blob 對象作為參數傳入這些方法,然后以指定的格式返回。
- `FileReader.readAsText()`:返回文本,需要指定文本編碼,默認為 UTF-8。
- `FileReader.readAsArrayBuffer()`:返回 ArrayBuffer 對象。
- `FileReader.readAsDataURL()`:返回 Data URL。
- `FileReader.readAsBinaryString()`:返回原始的二進制字符串。
下面是`FileReader.readAsText()`方法的例子,用來讀取文本文件。
```javascript
// 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);
};
}
```
上面代碼中,通過指定 FileReader 實例對象的`onload`監聽函數,在實例的`result`屬性上拿到文件內容。
下面是`FileReader.readAsArrayBuffer()`方法的例子,用于讀取二進制文件。
```javascript
// HTML 代碼如下
// <input type="file" onchange="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);
};
}
```
- 前言
- 入門篇
- 導論
- 歷史
- 基本語法
- 數據類型
- 概述
- null,undefined 和布爾值
- 數值
- 字符串
- 對象
- 函數
- 數組
- 運算符
- 算術運算符
- 比較運算符
- 布爾運算符
- 二進制位運算符
- 其他運算符,運算順序
- 語法專題
- 數據類型的轉換
- 錯誤處理機制
- 編程風格
- console 對象與控制臺
- 標準庫
- Object 對象
- 屬性描述對象
- Array 對象
- 包裝對象
- Boolean 對象
- Number 對象
- String 對象
- Math 對象
- Date 對象
- RegExp 對象
- JSON 對象
- 面向對象編程
- 實例對象與 new 命令
- this 關鍵字
- 對象的繼承
- Object 對象的相關方法
- 嚴格模式
- 異步操作
- 概述
- 定時器
- Promise 對象
- DOM
- 概述
- Node 接口
- NodeList 接口,HTMLCollection 接口
- ParentNode 接口,ChildNode 接口
- Document 節點
- Element 節點
- 屬性的操作
- Text 節點和 DocumentFragment 節點
- CSS 操作
- Mutation Observer API
- 事件
- EventTarget 接口
- 事件模型
- Event 對象
- 鼠標事件
- 鍵盤事件
- 進度事件
- 表單事件
- 觸摸事件
- 拖拉事件
- 其他常見事件
- GlobalEventHandlers 接口
- 瀏覽器模型
- 瀏覽器模型概述
- window 對象
- Navigator 對象,Screen 對象
- Cookie
- XMLHttpRequest 對象
- 同源限制
- CORS 通信
- Storage 接口
- History 對象
- Location 對象,URL 對象,URLSearchParams 對象
- ArrayBuffer 對象,Blob 對象
- File 對象,FileList 對象,FileReader 對象
- 表單,FormData 對象
- IndexedDB API
- Web Worker
- 附錄:網頁元素接口
- a
- img
- form
- input
- button
- option
- video,audio