Simonzhangs' blog Simonzhangs' blog
首页
  • 前端文章

    • HTML
    • CSS
    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • JS设计模式总结
  • 《Vue》
  • 《React》
  • 《TypeScript 从零实现 axios》
  • TypeScript
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • apple music
  • extension
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Simonzhangs

前端学习探索者
首页
  • 前端文章

    • HTML
    • CSS
    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • JS设计模式总结
  • 《Vue》
  • 《React》
  • 《TypeScript 从零实现 axios》
  • TypeScript
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • apple music
  • extension
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 前端Base64编码知识

    • Base64 起源
      • Base64 编码 64 的含义
        • Base64 编码原理
          • Base64 优缺点
            • Base64 编码和解码
              • Base64 应用场景
                • 1. canvas 图片生成
                • 2. 文件读取
                • 3. JWT
                • 4. 网站图片和小图片
                • 5. 简单的数据加密
              • 补充 -- 前端编码知识
                • 1. 比特和字节
                • 2. 获得字符的 Unicode 码点
                • 3. 进制转换
              • 总结
              simonzhangs
              2022-05-17
              随笔
              目录

              前端Base64编码知识

              # Base64 起源

              为什么会有 Base64 编码呢?

              因为有些网络传送渠道并不支持所有的字节,例如传统的邮件只支持可见字符的传送,像 ASCII 码的控制字符就不能通过邮件传送。这样用途就受到了很大的限制,比如图片二进制流的每个字节不可能全部是可见字符,所以就传送不了。

              最好的方法就是在不改变传统协议的情况下,做一种扩展方案来支持二进制文件的传送,把不可打印的字符也能用可打印字符来表示,问题就解决了。Base64 编码应运而生,Base64 就是一种基于 64 个可打印字符来表示二进制数据的表示方法。

              # Base64 编码 64 的含义

              所以说 base64 中 64 指的就是 64 个可打印字符(ASCII 编码)。

              • A-Z 26
              • a-z 26
              • 0-9 10
              • + / 2

              # Base64 编码原理

              因为 base64 编码只有 64 个字符,用 6 个比特表示就可以了,而正常英文字符是采用 ASCII 编码方式,一个字母占一个字节,即 8 个比特位,所以 base 编码时候,会将 3 字节转换为四字节,遇到转换过程中不够三字节时,会自己在后面补上=,所以说编码后体积至少变大 1/3。

              6 个有效 bit 来表示传统字符的 8 个 bit 呢?8 和 6 的最小公倍数是 24,也就是说 3 个传统字节可以由 4 个 Base64 字符来表示,保证有效位数是一样的,这样就多了 1/3 的字节数来弥补 Base64 只有 6 个有效 bit 的不足。

              # Base64 优缺点

              优点:

              1. 可以将二进制数据(比如图片)转化为可打印字符,方便传输数据;
              2. 对数据进行简单的加密,肉眼是安全的;
              3. 如果是在 html 或者 css 处理图片,可以减少 http 请求。

              缺点:

              1. 内容编码后体积变大, 至少 1/3(因为是三字节变成四个字节,当只有一个字节的时候,也至少会变成三个字节);
              2. 编码和解码需要额外工作量。

              # Base64 编码和解码

              # Base64 应用场景

              # 1. canvas 图片生成

              canvas 的 toDataURL 可以把 canvas 的画布内容转 base64 编码格式包含图片展示的 data URI。

              const ctx = canvasEl.getContext("2d");
              // ...... other code
              const dataUrl = canvasEl.toDataURL();
              
              // data:image/png;base64,iVBORw0KGgoAAAANSUhE.........
              
              1
              2
              3
              4
              5

              # 2. 文件读取

              FileReader 的 readAsDataURL 可以把上传的文件转为 base64 格式的 data URI,比较常见的场景是用户头像的剪裁和上传。

              # 3. JWT

              JWT 由 header, payload,signature 三部分组成,是通过base64进行的编码,前两个解码后,都是可以明文看见的。

              # 4. 网站图片和小图片

              移动端网站图标优化,还有小图片使用场景,比如img标签,背景图等。

              img标签:

              <img src="data:image/png;base64,iVBORw0KGgoAAAA......." />
              
              1

              css背景图:

              .bg{
                  background: url(data:image/png;base64,iVBORw0KGgoAAAA.......)
              }
              
              1
              2
              3

              # 5. 简单的数据加密

              当然这不是好方法,但是至少让你不好解读。

              # 补充 -- 前端编码知识

              # 1. 比特和字节

              比特又叫位。 在计算机的世界里,信息的表示方式只有 0 和 1, 其可以表示两种状态。一位二进制可以表示两状态, N 位可以表示 2^N 种状态。

              一个字节(Byte)有 8 位(Bit),所以一个字节可以表示 2^8 = 256 种状态。

              # 2. 获得字符的 Unicode 码点

              String.prototype.charCodeAt()方法可以获取字符的码点,获取范围为 0~65535,注意这里获取到的是 Unicode 的码点,不同的编码方式编码之后会得到不同的结果。

              常见的编码方式是 UTF-8,还有 UTF-16、UTF-32,这几种编码方式都是基于 Unicode 字符集(全球通用的字符集合);还有 ASCII 编码是基于 ASCII 字符集(只有 128 个字符,欧美国家字符集合)的。其中 UTF-8 编码是兼容 ASCII 字符集的。这些编码原理可以参考我之前总结的文章:JavaScript 的字符编码 (opens new window)

              # 3. 进制转换

              10 进制转其他进制,可以通过 Number.prototype.toString(radix):

              (100).toString(2); // 1100100
              (100).toString(16); // 64, 也等于 ox64
              
              1
              2

              其他进制转为 10 进制,可以通过 parseInt(string, radix),radix 表示当前字符串的进制:

              parseInt("10000000", 2); // 128
              parseInt("10", 16); // 16
              
              1
              2

              这里额外提一下一元操作符号+可以把字符串转为数字,后面也会用到,之前提到的 0b,0o,0x 这里都会生效。

              +"1000" + // 1000
                "0b10000000" + // 128
                "0o10" + // 8
                "0x10"; // 16
              
              1
              2
              3
              4

              # 总结

              说起 Base64 编码可能有些奇怪,因为大多数的编码都是由字符转化成二进制的过程,而从二进制转成字符的过程称为解码。而 Base64 的概念就恰好反了,由二进制转到字符称为编码,由字符到二进制称为解码。

              Base64 编码主要用在传输、存储、表示二进制等领域,还可以用来加密,但是这种加密比较简单,只是一眼看上去不知道什么内容罢了,当然也可以对 Base64 的字符序列进行定制来进行加密。

              Base64 编码是从二进制到字符的过程,像一些中文字符用不同的编码转为二进制时,产生的二进制是不一样的,所以最终产生的 Base64 字符也不一样。例如"上网"对应 utf-8 格式的 Base64 编码是"5LiK572R",对应 GB2312 格式的 Base64 编码是"yc/N+A=="。


              参考文章:

              前端 Base64 编码知识,一文打尽,探索起源,追求真相。 (opens new window)

              Base64 原理 (opens new window)

              编辑 (opens new window)
              上次更新: 2022/06/16, 10:52:37
              最近更新
              01
              一些有意思的类比
              06-16
              02
              the-super-tiny-compiler解析
              06-06
              03
              计算机编译原理总概
              06-06
              更多文章>
              Theme by Vdoing | Copyright © 2021-2022
              蜀ICP备2021023197号-2
              Simonzhans | MIT License
              • 跟随系统
              • 浅色模式
              • 深色模式
              • 阅读模式
              • 飙升榜
              • 新歌榜
              • 云音乐民谣榜
              • 美国Billboard榜
              • UK排行榜周榜