ArrayBuffer轉base64詳解
先貼程式碼:
const base64String = window.btoa(String.fromCharCode(...new Uint8Array(buffer)))
看起來非常的簡潔,優美。那麼我們今天就來捋一捋,這個看似簡單的背後,蘊含了怎樣的原理。
首先我們得來說說arrayBuffer這回事。
在JavaScript中,有一個很常用的引用資料型別Array,你可以在裡面放字串、數字、物件、布林值等等等等。它存放在堆中,可以自由增減。
而ArrayBuffer我們叫它型別化陣列,它的誕生就是為了解決一個問題:操作二進位制資料。
只由0和1組成的二進位制資料往往是非常巨大的,上千個位元組可以說司空見慣,傳統的Array這時候處理起二進位制資料起來就顯得非常低效,所以ArrayBuffer出現了,它作為一塊專用的記憶體區域存放在棧中,取資料非常快。
我們現在通過new ArrayBuffer(10)初始化一個buffer例項,看看會得到什麼。
let buffer = new ArrayBuffer(10);
console.log(buffer);
ArrayBuffer(10) {} [[Int8Array]]: Int8Array(10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [[Int16Array]]: Int16Array(5) [0, 0, 0, 0, 0] [[Uint8Array]]: Uint8Array(10) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] byteLength: 10 __proto__: ArrayBuffer
可以看到在ArrayBuffer中,主要存放了幾個“檢視”,Int8Array表示8位有符號整數陣列,Int16Array表示16位有符號整數陣列,Uint8Array則表示8位無符號整數陣列。
當然,如果比如說我們想取出Int8Array這個陣列來,是不能直接通過buffer.Int8Array來取的。這是因為ArrayBuffer不能直接通過下標去讀寫,我們需要把它轉成一個型別化陣列(TypedArray)。
const myTypedArray = new Uint8Array(buffer)
轉化完之後,我們我們不僅可以通過下標去對型別化陣列進行索引,也可以獲取其length,當然TypedArray仍與普通的Array存在細微的區別,那就是假設我們用超出邊界的索引語法去獲取陣列元素時,
TypedArray並不會去原型鏈中進行查詢。
現在我們已經拿到了這個型別化陣列,是時候把它轉成普通字串了。看看String.fromCharCode這個函式,它接受的引數為一堆程式碼單元序列,輸出一個普通字串。而我們剛剛得到的型別化陣列,裡
面存放的正是程式碼單元。
const str = String.fromCharCode(...myTypedArray)
這裡我們用拓展運算子...把型別陣列的程式碼單元解出來,一次性轉完,得到一個普通的字串。
最後,我們需要藉助一個window物件的方法,也就是btoa方法,它的作用是:把一個普通字串編碼成base-64格式的字串。
有時候後臺把圖片資源通過arrayBuffer傳給前端,這時候為了能正常顯示,我們還需要在轉化的base64字串前面拼接上data:image/jpeg;base64,
所以我們整理一下,可以得出這樣一個函式:
const arrayBufferToBase64Img = (buffer) => { const str = String.fromCharCode(...new Uint8Array(buffer)); return `data:image/jpeg;base64,${window.btoa(str)}`; }
總結
得到一個ArrayBuffer ---> 轉成型別化陣列以正常讀取 --> 轉成普通字串 --> 轉成base64字串
&n