参考
- https://www.jb51.net/article/95352.htm
- https://blog.csdn.net/weixin_42420703/article/details/81384901
介绍
为什么会有Base64编码呢?因为有些网络传送渠道并不支持所有的字节,例如传统的邮件只支持可见字符的传送,像ASCII码的控制字符就 不能通过邮件传送。这样用途就受到了很大的限制,比如图片二进制流的每个字节不可能全部是可见字符,所以就传送不了。最好的方法就是在不改变传统协议的情 况下,做一种扩展方案来支持二进制文件的传送。把不可打印的字符也能用可打印字符来表示,问题就解决了。Base64编码应运而生,Base64就是一种 基于64个可打印字符来表示二进制数据的表示方法。
所谓Base64,就是选出64个字符作为一个基本字符集(A-Z,a-z,0-9,+,/,再加上作为垫字的”=”,实际是65个字符),其它所有符号都转换成这个字符集中的字符。- 第一步,将每三个字节作为一组,一共是24个二进制位。
- 第二步,将这24个二进制位分为四组,每个组有6个二进制位。
- 第三步,在每组前面加两个00,扩展成32个二进制位,即四个字节。
- 第四步,根据下表,得到扩展后的每个字节的对应符号,这就是Base64的编码值。
如何编码
例如:
“dog”
d: ASCII值 100 ,二进制为 0110 0100
o: ASCII值 111 ,二进制为 0110 1111
g: ASCII值 103,二进制为 0110 0111
这24个二进制位 0110 0100 0110 1111 0110 0111 分为四组:
011001 000110 111101 100111
每组前面加两个00,即:
00011001 00000110 00111101 00100111
对应码值分别为:25、6、61、39
查找下表,可以知道得到编码后的字符串为:ZG9n
那如果字节数不足3呢?
a)2个字节的情况:将这2个字节的一共16个二进制位,按照上面的规则,转成三组(6,6,4),最后一组除了前面加两个0以外,后面也要加两个0。这样得到一个三位的Base64编码,再在末尾补上一个”=”号。
比如,“Ma”这个字符串是两个字节,可以转化成三组00010011、00010110、00000100以后,对应Base64值分别为T、W、E,再补上一个”=”号,因此”Ma”的Base64编码就是TWE=。
b)1个字节的情况:将这1个字节的8个二进制位,按照上面的规则转成2组(6,2),最后一组除了前面加二个0以外,后面再加4个0。这样得到一个二位的Base64编码,再在末尾补上两个”=”号。
比如,“M”这个字母是一个字节,可以转化为二组00010011、00010000,对应的Base64值分别为T、Q,再补上二个”=”号,因此”M”的Base64编码就是TQ==
如何解码
了解了编码规则之后,解码就很容易理解了,就是编码过程的逆过程
- 第一步,将每4个字符为一组,查找上表,找到每个字符对应的ASCII值
- 第二步,将4个ASCII值写成二进制形式,并将每个二进制的前2个00去掉
- 第三步,将剩下的24位二进制位分成3份,即3个字节
- 第四步,查找ASCII值表(下表),找到每个字节对应的字符。
javascript中实现Base64编码解码
atob、btoa
window有两个函数atob、btoa,但是这两个函数并不支持Unicode字符的编码,需结合encodeURIComponent、decodeURIComponent函数来使用
btoa
binary to ascii,用于将binary数据用ascii码表示。常用于编码字符串。
1 | var str = "This is a string"; |
但是不能编码Unicode字符
1 | var str = "hello, 中国"; |
atob
ascii to binary,用于将ascii码解析成binary数据。用于解码Base64编码的字符串。
1 | var encoded_str = "VGhpcyBpcyBhIHN0cmluZw=="; |
如何让btoa支持Unicode字符编码
编码时,先用encodeURIComponent对字符串进行编码,再进行btoa进行Base64编码
解码时,先用atob对Base64编码的串进行解码,再用decodeURIComponent对字符串进行解码
1 | var str = "hello,中国"; |
通用的编解码方法
对于IE9不支持这两种编码解码方式,可以使用公共类库来兼容IE9:
如下函数实现了Base64、Hex、Bytes、String之间的互相转换
1 | var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', |
1 | var raw_hex = 'f0c6'; |
Node.js中的Base64编码和解码
不幸的是,Node.js不支持用于Base64编码的标准JavaScript函数,例如atob()和btoa()。这些方法是窗口对象的一部分,仅在浏览器中可用。
幸运的是,Node.js提供了一个称为Buffer的本地模块,可用于执行Base64编码和解码。缓冲区可用作全局对象,这意味着您无需在应用程序中显式包含此模块。
在内部,Buffer以字节序列的形式表示二进制数据。 Buffer对象提供了几种方法来执行不同的编码和解码转换。这包括往返于UTF-8,UCS2,Base64,ASCII,UTF-16甚至HEX编码方案。
让我们看下面的示例,这些示例解释了如何使用Buffer对象在Node.js应用程序中执行Base64编码和解码。
Base64 编码
要将字符串转换为Base64编码的字符串,我们首先需要使用Buffer.from()方法根据给定的字符串创建一个缓冲区。 此方法采用两个参数,即纯文本字符串和字符编码,并为给定的编码创建缓冲区或二进制数据数组。 如果未指定字符编码,则将使用UTF-8作为默认值。
这里有一个例子:
1 | // plain-text string |
在上面的示例中,我们从字符串创建了一个缓冲区,并使用toString()方法将缓冲区编码为Base64字符串。 当您处理纯文本(UTF-8)字符串时,Buffer.from()中的第二个参数是可选的。
Base64解码
Base64解码过程与编码过程非常相似。 您需要做的就是通过使用base64作为Buffer.from()的第二个参数从Base64编码字符串中创建一个缓冲区,然后使用toString()方法将其解码为UTF-8字符串。
看起来是这样的:
1 | // Base64 encoded string |
base64编解码并转成hex
1 | var b = new Buffer('JavaScript'); |
1 | var b = new Buffer('SmF2YVNjcmlwdA==', 'base64') |
node.js编码解码图片
1 | var fs = require('fs'); |
结论
这就是Node.js中Base64编码和解码的全部内容。 我们研究了如何使用本机Buffer模块在Node.js应用程序中执行Base64编码和解码。 Buffer对象不仅限于Base64转换。 您甚至可以使用它执行ASCII,HEX,UTF-16和UCS2编码和解码。
Base64编码的实际运用
前端在实现页面时,对于一些简单图片,通常会选择将图片内容直接内嵌在页面中,避免不必要的外部资源加载,增大页面加载时间,但是图片数据是二进制数据,该怎么嵌入呢?绝大多数现代浏览器都支持一种名为 Data URL 的特性,允许使用Base64对图片或其他文件的二进制数据进行编码,将其作为文本字符串嵌入网页中。
可以使用在线图片编码工具
http://tool.chinaz.com/tools/imgtobase/
例如我编码了一张图片之后,其编码结果如下:
1 | data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJQAAACRCAYAAAAl8ZFnAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJ0SURBVHhe7dYxalRRFIBhl+AKXEzqNNZuwzKNnVZTBRtJkyUELCysBRtxHdM9El5k4MkLpMhwYQb8rd5XfN053c+599U0TQtUBEVKUKQERUpQpARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERWrzQd3//rXMtzdP7n/+GM5wvk0HNV/vluXN6xf+XL0fznKezQa1XqbjmJ49fL0b7nDaZoMaXadnjx8/DHc4bbNBrdGMYlqt/6nRDqcJ6sjh8mKZ9vvhDqcJ6ojn7t8ISlApQQkqJShBpQQlqJSgBJUSlKBSghJUSlCCSglKUClBCSolKEGlBCWolKAElRKUoFKCElRKUIJKCUpQKUEJKiUoQaUEJaiUoASVEpSgUoISVEpQgkoJSlApQQkqJShBpQQlqJSgBJUSlKBSghJUSlCCSglKUClBCSolKEGlBCWolKAElRKUoFKCElRKUIJKCUpQKUEJKiUoQaUEJaiUoASVEpSgUoISVEpQgkoJSlApQQkqJShBpQQlqJSgBJUSlKBSghJUSlCCSglKUClBCSolKEGlBCWolKAElRKUoFKCElRqu0HtPgnqP9hsUA/fvw2Dmm9vhvOcZ7NBrQ7v3r6I6XB5sUz7/XCW82w6qNX85fPTMzdf78QU2HxQtARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERUpQpARFSlCkBEVKUKQERUpQhKblL8jJczAt5hHJAAAAAElFTkSuQmCC |
用此方式可以将图片直接内嵌到网页中:
1 | <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJQAAACRCA..."/> |