欢迎关注公众号“燕小书”,回复:“技术交流”进微信技术交流群,公众号会陆续发布优质文章。image.png

什么是Base64

首先base64 只是一套编码规则,是一种基于64个可打印字符来表示二进制数据的表示方法。常用于图片,文本等小文件进行编码。

以下来自维基百科:

Base64(基底64)是一种基于64个可打印字符来表示二进制数据的表示方法。由于image.png,所以每6个比特为一个单元,对应某个可打印字符。3个字节相当于24个比特,对应于4个Base64单元,即3个字节可由4个可打印字符来表示。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9,这样共有62个字符,此外两个可打印符号在不同的系统中而不同。一些如uuencode的其他编码方法,和之后BinHex的版本使用不同的64字符集来代表6个二进制数字,但是不被称为Base64。 Base64常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据,包括MIME电子邮件XML的一些复杂数据。

为什么要使用base64:

我们知道在计算机中任何数据都是按ascii码存储的,而ascii码的128~255之间的值是不可见字符。而在网络上交换数据时,比如说从A地传到B地,往往要经过多个路由设备,由于不同的设备对字符的处理方式有一些不同,这样那些不可见字符就有可能被处理错误,这是不利于传输的。所以就先把数据先做一个Base64编码,统统变成可见字。符,这样出错的可能性就大降低了。

总结一句话:base64编码的初衷是应用在文件传输中,主要是为了将ascii编码的不可字符转换为可见字符。

Base64 的编码规则

Base64 是在传统编码体系上的一种改进,因为要了解base64 我们首先要简单了解谢计算机编码的常识。

计算机编码

计算机中的基本单位:1bit(比特) = 1个二进制位;1byte(字节)= 8 bit

计算机中所有的数据都是二进制的,不同的编码方案只是只是数据的映射到二进制的规则不一样,常见的编码方式有ASCII编码,unicode、GBK、GB2312、UTF-8等。

主要看下ascii和utf-8
ascii 的规则就是用8个比特位标识128个字符。
image.png
utf-8 编码中,一个汉字 = 3 字节(24bit),并且对ascii进行了兼容。
UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间。
image.png

进阶到base64

1、基础数据转换为二进制

看下面例子:
文本:

我是周正

二进制:

  1. 11100110 10001000 10010001 11100110 10011000 10101111
  2. 11100101 10010001 10101000 11100110 10101101 10100011

2、对二进制数据按6位切割

首先以6bit为单位进行分隔,并给每个片段头部进行2bit补位 “00”:
代码:

  1. // 11100110 10001000 10010001 11100110 10011000 10101111 11100101 10010001 10101000 11100110 10101101 10100011
  2. function cutInPiceBin(list = [], size) {
  3. const cutTimes = list.length / size; // 需要切割的次数
  4. let piceQuene = [];
  5. for (let i = 0; i < cutTimes; i++) {
  6. piceQuene.unshift(list.splice(size * -1).join(''))
  7. }
  8. console.log(piceQuene.map(item => `00${item}`));
  9. return piceQuene.map(item => `00${item}`);
  10. }
  11. cutInPiceBin('11100110 10001000 10010001 11100110 10011000 10101111 11100101 10010001 10101000 11100110 10101101 10100011'.replace(/\s+/g, "").split(''), 6)

处理后的的数据:

  1. [
  2. '00111001', '00101000',
  3. '00100010', '00010001',
  4. '00111001', '00101001',
  5. '00100010', '00101111',
  6. '00111001', '00011001',
  7. '00000110', '00101000',
  8. '00111001', '00101010',
  9. '00110110', '00100011'
  10. ]

现在我们发现数据的长度由原来的128 bit变为了 16 8 bit。

3、按照映射表进行编码

首先转换为10进制表示:

  1. const binBase64 = cutInPiceBin('11100110 10001000 10010001 11100110 10011000 10101111 11100101 10010001 10101000 11100110 10101101 10100011'.replace(/\s+/g, "").split(''), 6);
  2. const decBase64 = binBase64.map(item => parseInt(item, 2))
  3. console.log('decBase64', decBase64);

输出:

  1. [
  2. 57, 40, 34, 17, 57, 41,
  3. 34, 47, 57, 25, 6, 40,
  4. 57, 42, 54, 35
  5. ]

按照映射表进行编码:

  1. 5oiR5piv5ZGo5q2j

image.png

4、验证一下

image.png

Base64在前端中应用

在前端中最常见的使用Base64来处理图片—-将图片的url替换成Base64格式的dataUrl。

首先了解下dateUrl的概念。

dataUrl

概念

Data URL给了我们一种很巧妙的将图片“嵌入”到HTML中的方法。跟传统的用img标记将服务器上的图片引用到页面中的方式不一样,在Data URL协议中,图片被转换成base64编码的字符串形式,并存储在URL中,冠以mime-type。本文中,我将介绍如何巧妙的使用Data URL优化网站加载速度和执行效率

简单来说url大概分为两种:

  • 普通url (每个url指向服务器的一个资源,需发送请求获取该资源)
  • dataUrl (即前缀为 data: 协议的 URL,其允许内容创建者向文档中嵌入小文件,不进行资源请求)

    语法

    Data URLs 由四个部分组成:前缀 (data:)、指示数据类型的 MIME 类型、如果非文本则为可选的base64标记、数据本身:
    1. data:[<mediatype>][;base64],<data>

    图片链接url表示

  1. <img src="data:image/gif;base64,R0lGODlhMwAxAIAAAAAAAP///
  2. yH5BAAAAAAALAAAAAAzADEAAAK8jI+pBr0PowytzotTtbm/DTqQ6C3hGX
  3. ElcraA9jIr66ozVpM3nseUvYP1UEHF0FUUHkNJxhLZfEJNvol06tzwrgd
  4. LbXsFZYmSMPnHLB+zNJFbq15+SOf50+6rG7lKOjwV1ibGdhHYRVYVJ9Wn
  5. k2HWtLdIWMSH9lfyODZoZTb4xdnpxQSEF9oyOWIqp6gaI9pI1Qo7BijbF
  6. ZkoaAtEeiiLeKn72xM7vMZofJy8zJys2UxsCT3kO229LH1tXAAAOw==">

image.png

优缺点分析

优点:

  1. 提升性能: 网页上的每一个图片,都是需要消耗一个 http 请求下载而来的, 图片的下载始终都要向服务器发出请求,要是图片的下载不用向服务器发出请求,base64可以随着 HTML 的下载同时下载到本地.减少https请求。
  2. 加密: 让用户一眼看不出图片内容 , 只能看到编码。
  3. 方便引用: 在多个文件同时使用某些图片时, 可以把图片转为base64格式的文件, 把样式放在全局中, 比如common.css, 以后在用的时候就可以直接加类名, 二不需要多层找文件路径, 会提升效率。

    缺点:

    Base64转换的缺点是显而易见的:编码后体积增大。
    前面我们转化的例子可以看出,转化后又128bit变为了168 bit。
    基本转换关系为: ```javascript preBit 8 = afterBit 6
  • preBit: 转化前的体积
  • afterBit: 转化后的体积 ```

体积增大了 1/3,因为base64只是个编码一些小文本,不适合大文本编码(如视频)。