BASE64原理

简介

  • 前端在做首屏优化时,常常把小图片转码成BASE64格式
  • 浏览器原生提供了btoa(encode to base64) 和atob (decode)的方法
  • 这里说一下编码原理,用于理解为什么编码后体积更大

编码原理

  • 取字符的ASCII的二进制码,每个字符一个字节8个比特位
如A,对应96,8位二进制为
01100001
  • 每3个字符为一组,共3*8=24位,拆分为4个6位,每一个6位最高位补零成新的字节,这个字节共有2^6=64种可能,所以叫base64.
  • 这64个数分别用A-Za-z0-9, ‘+’, ‘/’ 表示
  • 原字符长度如果不被3整除,则将余下字符进行拆分。
    • 剩1个字符时, 8位后补4个0凑够12位,可以拆成两个字节,最后补两个‘=’号占位,凑成4个字节
    如剩a,
    -> 01100001 
    -> 011000     010000 // 末尾补4个0
    ->  00011000 00010000 // 前增加两个0
    -> 24 16
    -> Y Q // 在base64的表中查到为YQ
    -> YQ==
    
    • 剩2个字符串,共16位,后补2个0,凑够18位,可以拆成3个字节,最后补一个‘=’占位,凑成4个字节
  • 从上面的规则可知道,基本上每个字节都增加了原有的1/3, 所以总体编码后增长了3分之一

代码实现

  • base64表
var table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".split('');
  • encode
function encode(str) {
   // 除3, 3字节转4字节
   if (typeof str !== 'string') {
      throw new Error('string type require');
   }
   var res = [];
   str.split('').forEach((i)=>{
      // 转2进制,凑够8位
      var str = i.charCodeAt().toString(2);
      while(str.length%8) {
         str = '0' + str;
      }
      res.push( str);
   });

   var  plus = res.length %3; // 余数
   if (plus ===1) {
      res.push('0000');
   }
   if (plus ===2) {
      res.push('00');
   }

   var s = res.join('').match(/(\d{6})/g).map((item)=>{
     // 按6拆分
      var index = parseInt(item, 2);
      return table[index]
   });

   if (plus ===1) {
      s.push('==');
   }
   if (plus ===2) {
      s.push('=');
   }
   return s.join('');
}
  • decode
function decode (base) {
   // 求plus;
   // 还原
   var plus = 0;
   var code = [];
   base.split('').forEach((item)=>{
      var index = table.indexOf(item);
      if (index === 64) {
         plus++;
         return;
      }
      // 转成2进制, 补全6位
      str = Number(index).toString(2);
      while (str.length%6) {
         str = '0' + str;
      }
      code.push(str);
   });
   var s= code.join('');
   if (plus) {
     // 切割末尾的0
     s=s.slice(0, s.length - 2 * plus);
   }
   return s.match(/(\d{8})/g).map((item)=>{
      return String.fromCharCode(parseInt(item,2));
   }).join('');
}

测试

encode('test');// "dGVzdA=="
decode('dGVzdA=='); // "test"

// 原生
btoa('test'); //"dGVzdA=="
atob('dGVzdA=='); //"test"
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值