Base64 是一种基于 64 个可打印字符来表示二进制数据的表示方法。可打印字符包括字母 A-Z、a-z、数字 0-9,这样共有 62 个字符,此外两个可打印符号在不同的系统中而不同。
由于以 2 为底 64 的对数为 6,所以以每 6 个比特为一个单元,对应某个可打印字符。3 个字节相当于 24 个比特,对应于 4 个 Base64 单元,即 3 个字节可由 4 个可打印字符来表示。
当下,Base64 常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据,包括 MIME 的电子邮件及 XML 的一些复杂数据。
数值 | 字符 | 数值 | 字符 | 数值 | 字符 | 数值 | 字符 |
---|---|---|---|---|---|---|---|
0 | A | 16 | Q | 32 | g | 48 | w |
1 | B | 17 | R | 33 | h | 49 | x |
2 | C | 18 | S | 34 | i | 50 | y |
3 | D | 19 | T | 35 | j | 51 | z |
4 | E | 20 | U | 36 | k | 52 | 0 |
5 | F | 21 | V | 37 | l | 53 | 1 |
6 | G | 22 | W | 38 | m | 54 | 2 |
7 | H | 23 | X | 39 | n | 55 | 3 |
8 | I | 24 | Y | 40 | o | 56 | 4 |
9 | J | 25 | Z | 41 | p | 57 | 5 |
10 | K | 26 | a | 42 | q | 58 | 6 |
11 | L | 27 | b | 43 | r | 59 | 7 |
12 | M | 28 | c | 44 | s | 60 | 8 |
13 | N | 29 | d | 45 | t | 61 | 9 |
14 | O | 30 | e | 46 | u | 62 | + |
15 | P | 31 | f | 47 | v | 63 | / |
接下来我们对“Man”进行编码,首先通过 ASCII 码表获取对应字符的二进制,并依次并排,然后从前往后每隔 6 位作为一个单元,根据上面的索引表得到对应的字符。
文本 | M | a | n | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ASCII编码 | 77 | 97 | 110 | |||||||||||||||||||||
二进制位 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 0 |
索引 | 19 | 22 | 5 | 46 | ||||||||||||||||||||
Base64编码 | T | W | F | u |
如果要编码的字节数不能被 3 整除,最后会多出 1 个或 2 个字节,那么可以使用下面的方法进行处理:
=
号,代表补足的字节数。文本(1 Byte) | A | |||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
二进制位 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
二进制位(补0) | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Base64编码 | Q | Q | = | = | ||||||||||||||||||||
文本(2 Byte) | B | C | ||||||||||||||||||||||
二进制位 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
二进制位(补0) | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Base64编码 | Q | k | M | = |
在 JavaScript 中,有两个函数被分别用来处理解码和编码 Base64 字符串:
以上面编码部分的例子为例:
btoa(‘Man‘); // "TWFu"
btoa(‘A‘); // "QQ=="
btoa(‘BC‘); // "QkM="
atob(‘TWFu‘); // "Man"
atob(‘QQ==‘); // "A"
atob(‘QkM=‘); // "BC"
按照设计,Base64 需要二进制数据作为其输入。就 JavaScript 字符串而言,这意味着如果将字符串传递到 btoa()
中,其中包含占用多个字节的字符,则会出现错误,因为这不被视为二进制数据:
btoa(String.fromCharCode(255)); // "/w=="
btoa(String.fromCharCode(256)); // error
如果需要使用 btoa()
将 Unicode 文本编码为 ASCII,一个选项是转换字符串,使每个 16 位单元只占用一个字节。例如:
function toBinary(string) {
const codeUnits = new Uint16Array(string.length);
for (let i = 0; i < codeUnits.length; i++) {
codeUnits[i] = string.charCodeAt(i);
}
return String.fromCharCode(...new Uint8Array(codeUnits.buffer));
}
// a string that contains characters occupying > 1 byte
const myString = ‘?‘;
const encoded = btoa(toBinary(myString));
如果您这样做,当你解码时也必须需要反转已解的码字符串。
在日常使用中,我们经常会通过 Data URLs 接触到 Base64 编码,Data URLs 是前缀为 data:
协议的 URL,其允许内容创建者向文档中嵌入小文件。
Data URLs 由四个部分组成:前缀(data:)、指示数据类型的 MIME 类型、如果非文本则为可选的 Base64 标记、数据本身:
data:[<mediatype>][;base64],<data>
如果数据是文本类型,你可以直接将文本嵌入 (根据文档类型,使用合适的实体字符或转义字符)。如果是二进制数据,你就可以将数据进行 Base64 编码之后再进行嵌入。
比如我们可以借此实现图片预览:
<input id="fileEl" type="file" />
<script>
fileEl.addEventListener(‘change‘, handleChange);
function handleChange(ev) {
const fileReader = new FileReader();
const file = ev.target.files[0];
fileReader.onload = handleLoad;
fileReader.readAsDataURL(file); // 获取 DataURL
}
function handleLoad(ev) {
const imgeEl = document.createElement(‘img‘);
imgeEl.src = ev.target.result;
document.body.appendChild(imgeEl);
}
</script>
另外,还比较常见的情景就是我们在使用 Webpack 做优化时,可以通过 url-loader
在文件大小低于指定的限制时,可以返回一个 DataURL,借此减少不必要的 HTTP 请求。
除了上面的例子外,Base64 还存在其它不少场景中,比如 HTMLCanvasElement.toDataURL() 方法也可以返回一个包含图片展示的 data URI:
canvas.toDataURL(type /* 图片格式 */, encoderOptions /* 图片的质量 */);
或者来自字节数组:
const btoa = (str) => Buffer.from(str, ‘binary‘).toString(‘base64‘);
或者 ...
原文:https://www.cnblogs.com/dongwanhong/p/14828563.html