[TOC]
* * * * *
### 一、base64定義
[維基百科](https://zh.wikipedia.org/wiki/Base64) 上定義Base64是一種基于64個可打印字符(可見字符)來表示二進制數據的表示方法。由于 2^6 =64 ,所以每6個比特為一個單元,對應某個可打印字符。3個字節有24個比特,對應于4個Base64單元,即3個字節可由4個可打印字符來表示。它可用來作為電子郵件的傳輸編碼。在Base64中的可打印字符包括字母A-Z、a-z、數字0-9,這樣共有62個字符,此外兩個可打印符號在不同的系統中而不同。一些如uuencode的其他編碼方法,和之后BinHex的版本使用不同的64字符集來代表6個二進制數字,但是不被稱為Base64。
所謂Base64,就是說選出64個字符----小寫字母a-z、大寫字母A-Z、數字0-9、符號"+"、"/"(再加上作為墊字的"=",實際上是65個字符)----作為一個基本字符集。然后,其他所有符號都轉換成這個字符集中的字符。
### 二、js中 base64格式的編碼和解碼
#### 1. `btoa()`轉碼 和 `atob()` 解碼
js中提供了`btoa()`轉碼 和 `atob()` 解碼的方法處理 Base64格式
例如我們將 `http://webxiaoma.com/assets/images/manong.jpg` 進行編碼和解碼
```JavaScript
let url = "http://webxiaoma.com/assets/images/manong.jpg"
let btoaStr = btoa(url) // 將url編碼為Base64格式
//aHR0cDovL3dlYnhpYW9tYS5jb20vYXNzZXRzL2ltYWdlcy9tYW5vbmcuanBn
let atobStr = atob(btoaStr) //將Base64格式解碼
//http://webxiaoma.com/assets/images/manong.jpg
```
#### 2. `btoa()`轉碼 和 `atob()` 解碼的中文問題
當我們要將中文編碼為`Base64`格式后,在進行解碼是會亂碼,而在谷歌瀏覽器上在編碼中文時會直接報錯
```JavaScript
let url = "你好"
let btoaStr = btoa(url) // 在谷歌瀏覽器上報錯
```
我們這時需要借助 `encodeURIComponent` 和 `decodeURIComponent` 轉義中文字符,這里是由于` btoa `僅支持 `A`SCII` 字符序列,如果通過 `encodeURIComponent` 將中文字符編碼成ASCII字符序列,再通過 btoa 進行 base64 編碼。
```JavaScript
let url = "你好"
let btoaStr = encodeURIComponent(btoa(url)) //編碼: JUU0JUJEJUEwJUU1JUE1JUJE
let atobStr = decodeURIComponent(atob(btoaStr)) // 解碼: 你好
```
### 三、Base64編碼的原理
> 第一步,將每三個字節作為一組,一共是24個二進制位。
> 第二步,將這24個二進制位分為四組,每個組有6個二進制位。
> 第三步,在每組前面加兩個00,擴展成32個二進制位,即四個字節。
> 第四步,根據下表,得到擴展后的每個字節的對應符號,這就是Base64的編碼值。

這里需要注意的是當字節數不足三個字節時,則這樣處理:
1. 二個字節的情況:將這二個字節的一共16個二進制位,按照上面的規則,轉成三組,最后一組除了前面加兩個0以外,后面也要加兩個0。這樣得到一個三位的Base64編碼,再在末尾補上一個"="號。
比如,"Ma"這個字符串是兩個字節,可以轉化成三組00010011、00010110、00010000以后,對應Base64值分別為T、W、E,再補上一個"="號,因此"Ma"的Base64編碼就是TWE=。
2. 一個字節的情況:將這一個字節的8個二進制位,按照上面的規則轉成二組,最后一組除了前面加二個0以外,后面再加4個0。這樣得到一個二位的Base64編碼,再在末尾補上兩個"="號。
比如,"M"這個字母是一個字節,可以轉化為二組00010011、00010000,對應的Base64值分別為T、Q,再補上二個"="號,因此"M"的Base64編碼就是TQ==。
### 參考文獻
[Base64筆記](http://www.ruanyifeng.com/blog/2008/06/base64.html)