过去一直没搞懂base64是什么,最近看了阮一峰的笔记后,自己查了部分资料后才搞明白是什么。原来base64也像我之前做的UTF-8笔记一样,进行了编码,是为了解决电子邮件中不能直接使用非ASCII码字符的规定的问题。当然,现在我们常常是在图片中使用base64,减少请求次数。
1、什么是base64
我们都知道,ASCII
码字符集只有128个字符,对于美国人可能还够用,但是对于其他国家来说就远远不够了。于是出现了Unicode
字符集,它几乎囊括了所有你能见到的文字。并且还在不断发展。但是Unicode
组织是在1988年才成立,那在这之前常用的字符集是什么?ASCII
字符集。所以1982年给电子邮件定规范的时候,就规定了电子邮件只能使用ASCII
字符。这当然不利于电子邮件发展,你想,你写一封电子邮件还得用英文写。。。因此1992年,工程师们决定扩展电子邮件的技术规范,提出一系列补充规范,出现了MIME
。MIME
使用了Quoted-printable
和Base64
对邮件重新进行了编码,将那些非ASCII
字符转成ASCII
字符,关于MIME
的介绍,可以看阮一峰的MIME笔记。这里主要介绍base64
。
2、base64的编码方式
好的,我们已经知道base64
是用来将非ASCII
字符转化为ASCII
字符的。那么它具体是怎么实现的呢?它的规则如下:
- 首先将每3个字节分为一组,这样就一共是24个二进制位
- 接着将24个二进制位分成4组,每组6个二进制位
- 再在每组前面补充2个0,这样每组就是8个二进制位,共有4个字节
- 最后每个字节根据下表一一对应,组合起来就是编码完成的base64
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w
15 P 32 g 49 x
16 Q 33 h 50 y
上表来自阮一峰-Base64笔记
举个例子,现在我们要把sea
转化为base64
。sea
由3个字母组成,每个字母对应一个字节。它们的ASCII
值分别是115
、101
、97
,转成二进制分别是01110011
、01100101
、01100001
。组合起来就是011100110110010101100001
,分成4组就是011100-110110-010101-100001
(这里为了区分使用-
进行了分割,后文类似)。再在每组前面添2个0,就是00011100-00110110-00010101-00100001
。转成10进制,28-54-21-33
,再根据上表对应得到base64
值为c2Vh
。
但是有时候字节数不是3的倍数,这样会余下1个或2个字节。这种情况的处理方法如下:
- 二个字节的情况:将这二个字节的一共16个二进制位,按照上面的规则,转成三组,最后一组除了前面加两个0以外,后面也要加两个0。这样得到一个三位的Base64编码,再在末尾补上一个"="号。
- 一个字节的情况:将这一个字节的8个二进制位,按照上面的规则转成二组,最后一组除了前面加二个0以外,后面再加4个0。这样得到一个二位的Base64编码,再在末尾补上两个"="号。
举个例子,如果我们要将se
转成base64
,根据上文我们知道它的二进制是01110011-01100101
,根据每组6位可以分为011100-110110-0101
,再由上面的规则可以写成00011100-00110110-00010100
,转成10进制为28-54-20
,这样base64
为c2U=
。别忘了最后的那个=
号。
如果要将s
转成base64
,根据上文我们知道它的二进制是01110011
,根据每组6位可以分为011100-11
,再由上面的规则可以写成00011100-00110000
,转成10进制为28-48
,这样base64
为cw==
。别忘了最后的那2个=
号。
上面的例子都是英文的,那么肯定有小伙伴要问了,中文怎么办?这里需要考虑到编码方式,汉字有多种编码方式,如gb2312、utf-8、gbk等等
。不同编码方式对应的base64
是不同的。不知道什么是编码可以看我的笔记。因为网页通常使用utf-8
编码,这里以utf-8
编码作为例子。
假设我们要把汉字好
转成base64
。步骤如下:
好
字的utf-8
编码是E5A5BD
,转成二进制是11100101-10100101-10111101
,按每6个一组为111001-011010-010110-111101
- 在每组的前面添加2个0,得到
00111001-00011010-00010110-00111101
,转成10进制为57-26-22-61
- 对应规则表得到
base64
为5aW9
那么我们每次想要转换base64
都要这么搞吗?当然不是的,网上有很多在线转化base64
的网站。例如:base64在线转化。在JavaScript中也有两个函数可以用于base64
编码和解码,分别是btoa()
和atob
。例如上面的例子,要对sea
进行base64
编码可以这样:btoa('sea')
。得到结果是c2Vh
,解码可以这样:atob('c2Vh')
,返回sea
。但是这两个函数只适用于ASCII
字符集里面的字符。就,,,没什么用。
3、base64的优缺点
base64
初衷是应用于电子邮件,将非ASCII
字符转化为ASCII
字符。但是现在常常用于图片的转化。在图片中我们可以这么使用:<img src="https://img-blog.csdnimg.cn/2022010703501249031.png" />
。其中data:image/png;base64,
为固定前缀,表示使用base64
,image/png
表示这是一个png
图片。同样,也可以用在背景图片中,url(https://img-blog.csdnimg.cn/2022010703501249031.png)
。
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAAAmJLR0QA/4ePzL8AAAKLSURBVEjHjZW/T1NRFMc/valY0FgWI0U0pUgCQWXgxyYOuEOiDPBHMEiMpQEkMWmJ2sGdjQQHGERWGXTERoOkQgJio9ZqXFqCWEjDJfe9Png/S793ae4532/PPefd+/VJXBCgh9s000AdsM9vvvGZDxSdqU6BBoboI+AiW+Q9i+QqCdQwzCB+JGlSfCHHHnCREO300IGPEq95xaG7QIgoESRvWbD/Tzk+xD187DBjiktjtcg5uSxnZaukwmqVs3JZzsmIkWNUEOI5QdaZYdetqyZcYpybFHikVyHKZ48S5BNTZ9Jhl0k+EmScmlOBYSJkSVA6k65QIkGWZkYMgRCDHJHkf1V0tIEmOWKAkC7wAD8rbFVNV9hiBT9DSqCWPiQLlvBjnhG07AR5yQvLzgKSO9QKugmQts39Mu3ETRL1JIhwzpKTI02AbkEnkLIV+JTvXD+RqCfONX7wxJalWJ2CMLBhCxWInUgY9Bh5W9YmEParTvLL0SQlEdckfB50yKoJCu3C7jmCp1V40XVWnXAJGPDh036pT94Tgn3twjphnN3cTisUa19oA2z0pMdM7bTjqhqmIAO0edLzlolYoVgZwRrQYwtNWVpnSEzasrqBNUGKIh3aMM393bZ0Xkls8NeSE6KDA1KqxaNyWY5WfIfcVpkltGtRop/WCgN14gb9lFjUr3OOJQQPXZ9ydwQYQ/BGfcH6hzRPhiai+Kui+4nSRIZ5Tp60Q+IU6GKiiioCTNBFgTgHWHyhhWnq+UmS7YpnH6OJPNN81TesxhIjXIWxZIifxu3WNsJA2dpW2TRZWxu9ZWtbYt7L2nQ0cp+7nHep4JB3LNrfDi977+UWEa5wAfjHH3ZYZ9Vh78AxZeQKo4xU7NcAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAAElFTkSuQmCC" />
但是base64
也有它的缺点,从上面的转化过程我们已经知道,一个3字节的东西转为base64
后会变成4字节,这样增加了文件体积。小的图片还好,如果是大图,就不推荐使用base64
了,因为会导致文件体积过大,增大了大约三分之一的体积。
以上。
4、参考链接
1. 阮一峰 - MIME笔记
2. 阮一峰 - Base笔记