相信無(wú)論是前端還是后端開發(fā)工程師,對(duì)于Base64都不會(huì)感到陌生,在開發(fā)中我們經(jīng)常會(huì)將一些小圖片以Base64的形式存儲(chǔ)和加載。然而知其然也要知其所以然,Base64究竟是什么,我們?yōu)槭裁匆褂肂ase64,以及Base64的優(yōu)缺點(diǎn)又是什么呢?今天我們就來(lái)聊一聊。
什么是Base64
首先Base64是一種編碼格式,普遍應(yīng)用于需要在網(wǎng)絡(luò)中存儲(chǔ)和傳輸?shù)亩M(jìn)制數(shù)據(jù)。為什么叫Base64呢,主要是因?yàn)檫@種編碼格式每個(gè)字節(jié)的前兩位只能是0,剩下只有6位可以表示,所以對(duì)于Base64來(lái)說(shuō),一個(gè)字節(jié)只能表示64種情況。Base64的名字由此而來(lái)。
為什么要存在Base64
但我們不難發(fā)現(xiàn),這樣的話這種編碼格式并不能充分利用存儲(chǔ)資源,是比較低效的,那為什么還要用Base64這種編碼呢?為什么不直接傳輸二進(jìn)制而要轉(zhuǎn)成Base64格式再去傳輸呢?
原因是因?yàn)閎ase64最早是用在郵件傳輸協(xié)議中的,當(dāng)時(shí)郵件傳輸協(xié)議只支持ascii字符傳遞,ascii碼可以用來(lái)表示所有的英文字符和數(shù)字還有一些符號(hào),但其中還存在很多不可見字符或者叫控制字符,不可見字符在傳輸過(guò)程中可能會(huì)產(chǎn)生一些錯(cuò)誤,如果郵件中只傳輸英文數(shù)字等,那么ascii是可以直接支持不會(huì)有問(wèn)題,但是如果你要在文件中傳輸一些二進(jìn)制文件,圖片,視頻等資源的時(shí)候,不可避免的轉(zhuǎn)成ascii的時(shí)候會(huì)出現(xiàn)非英文數(shù)字的情況,也就是上面所說(shuō)的不可見字符,這時(shí)就有可能會(huì)導(dǎo)致傳輸過(guò)程中出現(xiàn)問(wèn)題。
Base64就是用來(lái)解決這個(gè)問(wèn)題的,人們想到把二進(jìn)制劃分為多個(gè)3個(gè)字節(jié)的塊,把每3個(gè)字節(jié)(24位)轉(zhuǎn)換成4個(gè)6位,每個(gè)六位根據(jù)查表對(duì)應(yīng)一個(gè)ASCII符號(hào)。如下圖所示:
上圖是Base64的編碼字典
如上圖所示,比如我們有一個(gè)3個(gè)字節(jié)的數(shù)據(jù),轉(zhuǎn)成ascii碼以后就是第一行所示,但我們查詢ascii碼會(huì)發(fā)現(xiàn)第三個(gè)字節(jié)是個(gè)不可見字符,所以如果在曾經(jīng)的郵件傳輸協(xié)議中這么傳輸可能會(huì)在過(guò)程中產(chǎn)生一些錯(cuò)誤,于是我們需要轉(zhuǎn)成base64再去傳輸,根據(jù)Base64的轉(zhuǎn)化規(guī)則曾經(jīng)的三個(gè)字節(jié)就變成了4組6位的值,然后我們需要在每一組前面補(bǔ)充兩個(gè)0補(bǔ)齊字節(jié)長(zhǎng)度。于是根據(jù)Base64編碼之后我們打印出的結(jié)果就是S3qb這個(gè)字符串。
另外這個(gè)例子比較特殊,我們正好是個(gè)3字節(jié)數(shù)據(jù),如果1個(gè)字節(jié)或者2個(gè)字節(jié)時(shí),我們就會(huì)發(fā)現(xiàn)位數(shù)不能正好被6整除,不能整除就會(huì)是下面這個(gè)示例展示的樣子
如何編碼和解碼Base64
在 JAVAScript 中,有兩個(gè)函數(shù)被分別用來(lái)處理解碼和編碼 base64 字符串。
- btoa() — 字符串轉(zhuǎn) Base64編碼
- atob() — 通過(guò)Base64規(guī)則解碼成ascii字符串
使用Base64存儲(chǔ)和加載圖片好不好?
相信大家對(duì)于Base64的編解碼和原理已經(jīng)有了深入了解,最后我們簡(jiǎn)單聊聊在前端頁(yè)面中使用Base64加載圖片到底好不好。所有事情都有兩面性,沒有絕對(duì)的好不好,只有在某些特定場(chǎng)景下合不合適。我們來(lái)看看Base64加載圖片的優(yōu)劣點(diǎn):
資源大?。焊鶕?jù)我們上面提到的原理,我們很容易發(fā)現(xiàn)Base64會(huì)比正常資源要大三分之一,Gzip壓縮之后差距會(huì)縮小。
緩存方式:圖片資源很好緩存,但如果是base64的話,如果是在cssjs中引入可以跟文件一起進(jìn)行緩存,如果在html中直接引用則必須緩存html文件,所以緩存方便程度上肯定是圖片資源文件更方便緩存。
加載方式:html/css中引入base64會(huì)導(dǎo)致文件體積變大,從而導(dǎo)致首屏展示的比較慢,而用過(guò)圖片資源方式異步引入會(huì)首屏?xí)故镜谋容^快。但對(duì)于需要加載很多圖片的情況下,尤其是腳在很多小圖片小icon的情況下,如果不使用雪碧圖的方式就會(huì)造成請(qǐng)求量很大,在http1.1/1.0協(xié)議下,在不開啟keep-alive的情況下,會(huì)導(dǎo)致效率低下重復(fù)創(chuàng)建銷毀連接通道,并且瀏覽器存在請(qǐng)求線程限制,并且存在網(wǎng)絡(luò)io延遲,這種情況下base64效率更高,但如果你的應(yīng)用使用http2/3的協(xié)議,base64的優(yōu)勢(shì)就不大了。
結(jié)語(yǔ)
所以綜合來(lái)看Base64加載圖片的方式多數(shù)情況下并不是最優(yōu)選擇,只有在圖片比較小,比較獨(dú)立并不適合做成雪碧圖的情況下再去使用比較好。