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编码
。
参考博客: