窥探Base64

背景 最近在开发的时候我遇到了一个需求:在前端显示一张图片的size。当然,如果是本地上传的话,可以直接从file接口读出本地上传图片的大小,如果是用ajax去获取的资源,可以读取http协议的content-length字段。但是这张图片需要先进行一些处理(缩放,裁剪)。而这些处理我是用canvas来处理的(drawImage接口),然后用toDataURL导出处理过后的图片。该api导出的是Base64的字符串。也就是说我需要从这段Base64字符串计算出最后生成的图片的大小。
刚刚了解这个需求的时候,我第一反应是应该会有某个我不知道的web Api直接解决这个问题。但是我google了一下,发现这方面的问题并没有解决方案。后来我才反应过来,肯定是因为这个问题太简单了,各大社区都不屑于收录。
Base64原理 Base64是一种数据的转化方式。说白了,就是一种把二进制文件转化为ASCII字符串的算法。核心的思想是:把3个连续的字节(24bits)分拆成4组(每组由6个bit组成),然后给每组前面补充00,组成4个bytes。然后就很容易明白,为什么叫Base64。64就是2的6次方嘛,刚好对应6个bit。这6个bit将对应64个ASCII字符(如下图):
窥探Base64
文章图片
Paste_Image.png 假如字节数不是刚好3的倍数怎么办呢?
处理方法如下:

  1. 剩下一个字节的情况:首先在末尾补齐足够的二进制位(值为0),使其数量能被3整除,也就是说,在末尾添加4个零。然后分为2组,每组6个字节,进行Base64编码。最后在末尾添加2个填充符号,即2个=。
  2. 剩下两个字节的情况:首先在末尾补齐足够的二进制位(值为0),使其数量能被3整除,也就是说,在末尾添加2个零。然后分为3组,每组6个字节,进行Base64编码。最后在末尾添加1个填充符号,即1个=。
至于为什么要使用base64,它解决了什么问题,这个可以去看看下面参考Blog,TX的大牛说的很清楚!
解决方案 了解了Base64原理之后,刚刚的需求就很容易实现了。base64字符串的大小会比原文件大约三分之一!

const base64 = canvas.toDataURL('image/png');
const size = base64.length / 1024 / 4 * 3; // 最后以Kb为单位

参考Blog 【窥探Base64】腾讯大牛: http://eleveneat.com/2016/08/29/Base64/

    推荐阅读