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 文件的缓存。

写在最后

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

你点的每个赞,我都认真当成了喜欢

目录 缩略词 正文之前 1. 目的 2. 本文内容 3. 声明 1. 字符编码相关的背景知识 1.1. 拉丁字母 1.1.1. 我们的目标 1.2. 什么是字符编码 2. 字符编码标准 2.1. 只支持基本的拉丁字符的字符编码:ASCII 2.1.1. ASCII的由来 2.1.2. ASCII编码规则 2.1.2.1. ASCII字符集中的功能/控制字符 2.1.2.1.1. 什么是Function Code功能码或 Function Character功能字符 2.1.2.1.2. ASCII中的Function/Control Code功能字符的详细含义 2.1.2.1.2.1. 0 – NUL – NULl 字符/空字符 2.1.2.1.2.2. 1 – SOH – Start Of Heading 标题开始 2.1.2.1.2.3. 2 – STX,3 – ETX 2.1.2.1.2.4. 4 – EOT – End Of Transmission 传输结束 2.1.2.1.2.5. 5 – ENQ – ENQuiry 请求 2.1.2.1.2.6. 6 – ACK – ACKnowledgment 回应/响应 2.1.2.1.2.7. 7 – BEL – [audible] BELl 2.1.2.1.2.8. 8 – BS – BackSpace 退格键 2.1.2.1.2.9. 9 – HT – Horizontal Tab 水平制表符 2.1.2.1.2.10. 10 – LF – Line Feed 换行 2.1.2.1.2.11. 11 – VT – Vertical Tab 垂直制表符 2.1.2.1.2.12. 12 – FF – Form Feed 换页 2.1.2.1.2.13. 13 – CR – Carriage return 机器的滑动部分/底座 返回 -> 回车 2.1.2.1.2.14. 14 – SO,15 – SI 2.1.2.1.2.15. 16 – DLE – Data Link Escape 数据链路转义 2.1.2.1.2.16. 17 – DC1 – Device Control 1 / XON – Transmission on 2.1.2.1.2.17. 18 – DC2 – Device Control 2 2.1.2.1.2.18. 19 – DC3 – Device Control 3 / XOFF – Transmission off 传输中断 2.1.2.1.2.19. 20 – DC4 – Device Control 4 2.1.2.1.2.20. 21 – NAK – Negative AcKnowledgment 负面响应-> 无响应, 非正常响应 2.1.2.1.2.21. 22 – SYN – SYNchronous idle 2.1.2.1.2.22. 23 – ETB – End of Transmission Block 块传输中止 2.1.2.1.2.23. 24 – CAN – CANcel 取消 2.1.2.1.2.24. 25 – EM – End of Medium 已到介质末端,介质存储已满 2.1.2.1.2.25. 26 – SUB – SUBstitute character替补/替换 2.1.2.1.2.26. 27 – ESC – ESCape 逃离/取消 2.1.2.1.2.27. 28 – FS – File Separator 文件分隔符 2.1.2.1.2.28. 29 – GS – Group Separator分组符 2.1.2.1.2.29. 30 – RS – Record Separator记录分隔符 2.1.2.1.2.30. 31 – US – Unit Separator 单元分隔符 2.1.2.1.2.31. 32 – SP – White SPace 空格键 2.1.2.1.2.32. 127 – DEL – DELete 删除 2.1.2.1.3. 各种字符的标准的读法/叫法 2.1.3. ISO 646 2.2. 支持多种衍生拉丁字母的字符编码:EASCII和ISO 8859 2.2.1. EASCII 2.2.2. ISO 8859 2.2.2.1. ISO/IEC 8859出现的背景 2.2.2.2. ISO/IEC 8859的编码规则 2.2.2.3. ISO/IEC 8859的特点 2.2.2.4. ISO/IEC 6429 2.2.2.5. ISO 8859和ISO-8859的区别和联系 2.2.2.5.1. 原先的ISO 8859-1和我们常说的ISO 8859-1 2.3.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值