1、前言
在我之前的博客中,介绍有关ASCII的相关知识
中间有时会提到如何转换
但是对于Base64的概念,但没有细说,所以这期来简单聊聊Base64编码。
2、为什么使用Base64
我们知道,Ascii码的128~255之间的值是不可见字符。在网络上交换数据时,比如从A地传到B地,往往要经过多个路由设备,由于不同的设备对字符的处理方式有一些不同,这样那些不可见字符就有可能被处理错误,这是不利于传输的。所以就先把数据转为Base64编码,统统变成可见字符,这样出错的可能性就大降低了。
同时base64作为网络上最常见的用于传输8bit字节代码的编码方式之一。有时我们需要把二进制数据编码为适合放在URL中的形式。这时采用base64编码具有不可读性,即所编码的数据不会被人直接看出。除此之外,还可以放在请求头,响应头进行传输。
3、Base64的概念
Base64 就是指64个字符,包括大小写字母[A-Z、a-z],阿拉伯数字[0-9],还有两个字符[+、/],还有一个表示后缀的字符 [ = ],Base64就是指只能传输这64个字符 。
【注意】实际上Base64是65个字符
4、Base64的原理
4.1、编码规则
ASCII码, ASCII码的范围是0-127,其中0-31和127是控制字符,共33个。其余95个,即32-126是可打印字符,包括数字、大小写字母、常用符号等。Base64 就是将 ASCII码 用 Base64位字符表示。
编码规则:
- 第一步:将每3个字符作为一组,一共是24个二进制位
- 第二步:将这24个二进制位分为4组,每个组有6个二进制位
- 第三步:在每组前面加两个00,扩展成32个二进制位,即4个字符
- 第四步:根据下表,得到扩展后的每个字节的对应符号,这就是Base64的编码值

4.2、编码示例
(1)Base64编码实例一:
将字符串“dog"转为Base64编码:
- 第一步:d: ASCII值 100 ,二进制为 0110 0100;o: ASCII值 111 ,二进制为 0110 1111;g: ASCII值 103,二进制为 0110 0111(ASCII码可以上网搜那张对应表)
- 第二步:
将这24个二进制位:0110 0100 0110 1111 0110 0111 ,分为4组:011001 000110 111101 100111 - 第三步:
每组前面加两个00,即:00011001 00000110 00111101 00100111 - 第四步:查找对应的码值分别为:
25、6、61、39。查找上表,可以知道得到编码后的字符串为:ZG9n,所以字符串“dog”对应的Base64码值为“ZG9n”
(2)Base64编码实例二:
将字符串“Man"转为Base64编码,(这次我们以图来演示如何转换):
从上述两个例子可以得出结论:
- 6和8的最小公倍数是24,所以
Base64需要6个二进制位表示ASCII码8个二进制位,显然,我们需要补0 - 这样
4个Base64编码的6bit字符刚好能够表示3个传统的Ascii编码的8bit字符 base64编码传输会使得信息变大,数据体积通常是原数据的体积4/3
4.3、特殊情况
上面我们的例子都是3个字符的情况,那如果不满3个,该怎么做?
(1)2个字节的情况:将这2个字节的一共16个二进制位,按照上面的规则,转成三组(6,6,4),最后一组除了前面加两个0以外,后面也要加两个0。这样得到一个三位的Base64编码,再在末尾补上一个"="号。
比如:“Ma"这个字符串是两个字节,可以转化成三组00010011、00010110、00000100以后,对应Base64值分别为T、W、E,再补上一个”="号,因此"Ma"的Base64编码就是TWE=。
(2)1个字节的情况:将这1个字节的8个二进制位,按照上面的规则转成2组(6,2),最后一组除了前面加二个0以外,后面再加4个0。这样得到一个二位的Base64编码,再在末尾补上两个"="号。
比如:“M"这个字母是一个字节,可以转化为二组00010011、00010000,对应的Base64值分别为T、Q,再补上二个”="号,因此"M"的Base64编码就是TQ==。
如果上述文字理解起来比较麻烦,可以参考下图:
4.4、加码过程
Base64解码的过程比较简单。去掉末尾的等号=。剩下的Base64字符,每8bit组成一个8bit字节,最后剩余不足8位的丢弃即可
5、Base64的作用
- Base64编码是从
二进制 ------> 字符的过程 - 采用Base64编码具有
不可读性,需要解码后才能阅读。但是Base64不是加密,只是一种可被翻译的编码 - Base64编码可用于在
HTTP环境下传递较长的标识信息,用作HTTP表单和HTTP GET URL中的参数 - 当需要把
二进制数据放到url中时,采用base64具有不可读性比较合适
6、Base64的使用场景
6.1、图片的Base64编码
我们有时会看到,一些图片的地址并不是一个网络地址,而是一串字符串(如下图红框所示),这就是用Base64来表示该图片的地址。
图片的 base64 编码就是将一张图片数据编码成一串字符串,使用该字符串表示图片,从而无需图片地址。
这样做有什么意义呢?我们知道,我们所看到的网页上的每一个图片,都是需要消耗一个 http 请求下载而来的。要是图片的下载不用向服务器发出请求,而可以随着 HTML 的下载同时下载到本地那就太好了,而 base64 正好就可以满足。这里等于把图片变为一串编码,直接嵌在html里传递给了浏览器,浏览器不用再次请求图片了。
编码之后的字符串可以直接内联到HTML中显示,比如,我们一些体积比较小的图片,(注意:是图片足够小的情况下),就可以转换成 Base64编码,直接插入到图片的 src 路径中。
在css里面的写法:
#xxx_xxx {
background: url(data:image/gif;base64,R0lGODlhHAAmAKIHAKqqqsvLy0hISObm5vf394uLiwAAAP///yH5B…EoqQqJKAIBaQOVKHAXr3t7txgBjboSvB8EpLoFZywOAo3LFE5lYs/QW9LT1TRk1V7S2xYJADs=) no-repeat center;
}
在html里面img标签中的写法:
<img src="data:image/gif;base64,R0lGODlhHAAmAKIHAKqqqsvLy0hISObm5vf394uLiwAAAP///yH5B…EoqQqJKAIBaQOVKHAXr3t7txgBjboSvB8EpLoFZywOAo3LFE5lYs/QW9LT1TRk1V7S2xYJADs=">
(小秘密?)
诸如我们都熟悉的迅雷的“专用地址”,也是用 Base64 加密的:
thunder://QUFodHRwOi8vZG93bi5zYW5kY······1RodW5kZXI3LjEuNS4yMTUyLmV4ZVpa(不要复制我我真的不是种子)
6.2、部分背景图
我们经常会遇到一个场景,就是页面的背景图 background-image 。在很多地方,我们会制作一个很小的图片大概是几px * 几px,然后平铺它页面当背景图。
因为是背景图的缘故,所以无法将它放入雪碧图,而它却在网站的很多页面使用,这种图片往往只有几十字节,却需要一个 http 请求,十分不值得。那么此时将它转化为 base64 编码,何乐而不为?
下面()是一个只有 50 字节的2*2的的背景图。将其转化成 base64 编码,只有 100 多个字符,相比一个 http 请求,这种转换无疑更值得推崇:
7、Base64的优缺点
优点:
- Base64 的好处能够
减少一个图片的 HTTP 请求
缺点:
- 图片被
Base64编码之后,生成的字符串编码大小一般都会比原文件稍大一些。即便Base64 编码能够被gzip 压缩,压缩率能达到50% 以上,也会比原文件大。 图片不会导致关键渲染路径的阻塞,但是用Base64编码转换后的使用会增加 CSS 文件的体积,而CSS 文件体积的增大意味着会阻碍 CRP(CRP指关键渲染路径,具体可以查看博客 《前端性能优化 CRP》),影响页面渲染,增加用户使用白屏时长(HTML 和 CSS 会阻塞渲染,而图片不会)
CRP(Critical Rendering Path,关键渲染路径):当浏览器从服务器接收到一个HTML页面的请求时,到屏幕上渲染出来要经过很多个步骤。浏览器完成这一系列的运行,或者说渲染出来我们常常称之为“关键渲染路径”。
所以,要有取舍地使用base64。正常比较大的图片,都不可用Base64,因为塞进css里增大css文件阻塞渲染;对于一些极小的,简单的图片,我们可以使用Base64编码。
参考博客: