# [知識篇]WebAPIs - Blob
在WebRTC APIs - RTCDataChannel
中,傳輸數據時只能傳輸Blob
與ArrayBuffer
,剛好藉此機會,來了解開發時常用於檔案上傳處理(如照片上傳等)的兩種物件。
# Blob
Blob
(Binary large Object)物件,主要目的是提供可代表及操作與儲存 JavaScript native 以外的格式,所以能夠讀取binary data,例如利用Blob讀寫照片檔,但其保存的數據是不可改寫的(immutable)。
而我們常用在<input type=file>
來拿到的File
物件也是一種特殊的Blob
物件,其繼承了Blob的屬性。
Blob物件屬性:
size
: 表示儲存的資料,總共佔了多少位元(byte)。type
: 表示儲存的資料格式(MIME type)。
# 範例
這邊會舉例幾個常用情境:
- 透過
File
來讀取使用者系統中的資料。
const fileInput = document.querySelector('input[type=file]')
const { files } = fileInput
console.log(files)
- 透過
FileReader
來讀取Blob中的內容,並且能轉換成text/ArrayBuffer/...等格式。
const blob = new Blob(['<div><h1>Hello World</h1></div>'])
const getFileLoad = event => console.log('FileRead.onload ', event.target.result)
const fileReader = new FileReader();
// 成功load資料後觸發
fileReader.addEventListener('load', getFileLoad);
// 讀取並轉成ArrayBuffer
fileReader.readAsArrayBuffer(blob);
這邊實例化一個Blob物件,其建構式有兩個參數:
var newBlob = new Blob(array, options);
array
: 可以是ArrayBuffer, ArrayBufferView, Blob, USVString等這些物件組成的陣列。options
type
: 定義資料的MIME格式
透過
URL.createObjectUrl(Blob)
來產生對應的Blob url,用於Browser上的a tag
或是img src
,便於下載或是顯示圖片。
const blob = new Blob([JSON.stringify({hello: 'world'})], {type: 'application/json'})
const url = URL.createObjectURL(blob)
// 模擬檔案下載
const aTag = document.createElement('a')
aTag.href = url
aTag.download = 'JsonFile'
aTag.click()
// 清掉暫存
aTag.href = '';
URL.revokeObjectURL(url);
注意:
透過
URL.createObjectUrl
創建url時,如果沒有要使用了,要記得URL.revokeObjectURL()
,因為這是靜態方式,所以使用時會暫存,沒有清除的話會一直佔用著記憶體。Blob URL
只能夠在同個瀏覽器中使用,內容只有包含瀏覽器存放Blob object
的參考位置,方便某些API運用(如上傳時圖片預覽),並不包含實際檔案數據,所以不像Data URL
(base64)一樣有保存實際完整數據。利用
Blob.prototype.slice()
拆分檔案數據分次傳送。
const chunkSize = 10
let offset = 0
let blob = new Blob(['<div><h1>Hello World</h1></div>'])
const getFileLoad = event => {
offset += event.target.result.byteLength; // ArrayBuffer的單位是byteLength
console.log(offset)
if (offset < blob.size) {
readSlice(offset);
}
}
const fileReader = new FileReader();
// 成功load資料後觸發
fileReader.addEventListener('load', getFileLoad);
// 切分後讀取並轉成ArrayBuffer
const readSlice = o => {
const chunk = blob.slice(offset, o + chunkSize);
fileReader.readAsArrayBuffer(chunk);
};
readSlice(0)
利用Blob.prototype.slice()
複製的方式,達到切分的功能。
var newBlob = blob.slice(start, end, contentType);
# 特性
從幾個範例演示下來,可以發現Blob有幾個好處
- 使網頁透過js能夠讀寫使用者指定的檔案。
- 上傳比較大的檔案時,也能做切分,分次上傳。
- 可以轉成
ArrayBuffer
儲存成binary data。 - 透過
createObjectURL
的方式,轉成Blob URL後只要是能使用url的地方都能夠傳入(a href, img src...等),使用彈性增加。
# 支援度
參考:
# 總結
本章了解到:
- Blob適合用來操作文件檔案。
- Blob物件的內容必須透過
FileReader
讀取。 - 搭配FileReader能進行將Blob轉換成text/ArrayBuffer/DataUrl及切分傳輸..等用途。
- 經由
URL.createObjectURL
轉成Blob URL。