阅读 1821

Base64 编码入门教程

前言

  Base64 是一种基于 64 个可打印字符来表示二进制的表示方法。具体的 64 个字符如下图所示:

出现背景

  早期邮件传输协议基于 ASCII 文本,对于诸如图片、视频等二进制文件处理并不好。

ASCII 主要用于显示现代英文,到目前为止只定义了 128 个字符,包含控制字符和可显示字符。

  为了解决上述问题,Base64 编码顺势而生。

基础使用

  在浏览器环境下,可以使用 window.atob 和 window.btoa 方法,进行 Base64 和 UTF-8 之间的转化:

  const utf8ToBase64 = window.btoa('Hello World!');
  console.log(utf8ToBase64); // base64: SGVsbG8gV29ybGQh

  const base64ToUtf8 = window.atob(utf8ToBase64);
  console.log(base64ToUtf8); // UTF-8: Hello World!
复制代码

  在 Node.js 环境下,可以通过 Buffer 来完成两者之间的转化:

  const strToBase64 = Buffer.from('Hello World!''utf-8').toString('base64');
  console.log('base64: ', strToBase64); // base64:  SGVsbG8gV29ybGQh

  const str = Buffer.from(strToBase64, 'base64').toString('utf8');
  console.log('utf-8: ', str) // utf-8:  Hello World!
复制代码

实现原理

  Base64 编码的过程如下:

  • (1)首先对待编码字符串进行每 3 个字节分组,如果当前分组不够 3 个字节,则通过补零来构成 3 字节一组。
  • (2)将每组的 24 位按照 6 位划分,得到 4 个 6 位二进制数组。
  • (3)对每个 6 位二进制数组进行高位补零,形成 8 位二进制数数组。
  • (4)查表获取每个字节的十进制对应的字符。
  • (5)将(1)中补充的字节数兑换成 = 的个数,拼接到(4)得到的完整字符串的尾部。

  以 a 字符为例。

  a 对应 1 个字节,如果要完成分组,那么就需要用零补足两个字节:

  0 1 1 0 0 0 0 1
  ----------------
  0 0 0 0 0 0 0 0
  ----------------
  0 0 0 0 0 0 0 0
复制代码

  接下来需要将它们再按照 6 位划分:

  0 1 1 0 0 0
  -----------
  0 1 0 0 0 0
  -----------
  0 0 0 0 0 0
  -----------
  0 0 0 0 0 0
复制代码

  再进行高位补零补足 8 位,形成一个字节:

  0 0 0 1 1 0 0 0 --> 24
  ---------------
  0 0 0 1 0 0 0 0 --> 16
  ---------------
  0 0 0 0 0 0 0 0 --> 0
  ---------------
  0 0 0 0 0 0 0 0 --> 0
复制代码

  再根据每个字节的十进制值查表,得到字符串 YQ,由于用零补充了两个字节,所以加上两个 = ,那么最终转化的结果为:

  YQ==
复制代码

特点

  从上述实现原理中,可总结出 Base64 编码的几个特点:

  • Base64 编码结果的长度永远是 4 的整数倍。
  • Base64 编码结果至多包含两个 = 字符。
  • Base64 编码使原文的大小增加了 1/3 倍。

应用场景

  Base64 编码的第一种应用场景就是前面提到的邮件传输协议,不过随着时代的发展,邮件传输协议已经支持直接传输二进制数据,不再需要 Base64 或者其它编码方式。

HTTP2 也改进为二进制格式传输数据,使得协议解析起来更加高效。

  第二种应用场景:加密内容的输出。

  客户端在发起请求时,通常需要将内容进行加密处理,而最终加密输出的内容就是 Base64 编码格式。这里有一个特别需要注意的地方,当标准 Base64 编码的内容放在 URL 中传输的时候会出特殊的情况导致服务端解密失败。

URL编码器会把标准 Base64 编码中的 “/” 和 “+” 字符变为形如 “%XX” 的形式。

  所以客户端一般会将标准 Base64 编码中的 + 和 / 替换为 URL 安全的字符,例如 - 和 _ 。

  第三种应用场景:图片资源的显示。

  在浏览器环境下,不仅可以通过标准的 HTTP 或者 HTTPS 链接来显示图片,还可以通过 Data URLs 来显示图片:

  <img src="data:image/gif;base64,R0lGODlhMwAxAIAAAAAAAP///
  yH5BAAAAAAALhbstxgzADEAAAK8jI+pBr0PowytzotTtbm/DTqQ6C3hGX
  ElcraA9jIr66ozVpM3nseUvYP1UEHF0FUUHkNJxhLZfEJNvol06tzwrgd
  LbXsFZYmSMPnHLB+zNJF1215+SOf50+6rG7lKOjwV1ibGdhHYRVYVJ9Wn
  k2HWtLdIWMSH9lfyODZoZTb4xdnpxQSEF9oyOWIqp6gaI9pI1Qo7BijbF
  ZkoaAtEeiiLeKn72xM7vMZofJ23zJys2UxsCT3kO229LH1tXAAAOw=="
>

复制代码

  webpack 中的 url-loader 就提供了将图片转化为 Data URLs 的功能,一般会设置图片的大小限制,这主要是因为 Base64 处理之后的大小会增加 1/3 倍,所以图片太大的话,反而得不偿失。

  这种将图片内联到 HTML 或者 CSS 的方式,可以有效地减少请求数量,从而优化站点的网络请求。

  但是该方式也存在缺陷:

  • 体积增大,需要权衡对 HTML 和 CSS 的影响。
  • 无法充分利用缓存,依赖其内联的 HTML 和 CSS 文件的缓存。

写在最后

  最后,如果本文对您有帮助,欢迎关注(公众号【漫谈大前端】)、点赞、转发 ε=ε=ε=┏(゜ロ゜;)┛。

文章分类
前端
文章标签