Base64编码

一、Base64是怎么诞生的

互联网发展早期,电子邮件是最有效的应用。而电子邮件的SMTP传输协议在早期,只能用于传送7位的ASCII码,而ASCII码就是基于英语设计的,对于非英语国家的文字等资源就无法发送。为了解决这个问题,后来有了通用互联网邮件扩充MIME,增加了邮件的主体结构,定义了非ASCII码的编码传输规则,这就是Base64

二、基础定义

Base64是基于64个可打印字符来表示二进制数据的编解码方式。正因为可编解码,所以它主要的作用不在于安全性,而在于让内容能在各个网关间无错的传输。
这64个可打印字符包括大写字母A-Z、小写字母a-z、数字0-9共62个字符,再加上另外2个 + /。Base64是一种索引编码,每个字符都对应一个索引,具体的关系图,如下:

在这里插入图片描述

三、编码方式

由于64等于2的6次方,所以一个Base64字符实际上代表着6个二进制位(bit)。然而,二进制数据1个字节(byte)对应的是8比特(bit),因此,3字节(3 x 8 = 24比特)的字符串/二进制数据正好可以转换成4个Base64字符(4 x 6 = 24比特)。

具体的编码方式:

  • 将每3个字节作为一组,3个字节一共24个二进制位
  • 将这24个二进制位分为4组,每个组有6个二进制位
  • 在每组的6个二进制位前面补两个00,扩展成32个二进制位,即四个字节,每个字节对应的将是一个小于64的数字,即为字符编号
  • 再根据字符索引关系表,每个字符编号对应一个字符,就得到了Base64编码字符

在这里插入图片描述

上图中的字符串 you,经过转换后,得到的编码为: eW91

  • 体积增大
    我们可以看到,当3个字符进行Base64转换编码后,最后变成了4个字符。因为每个6比特位,都补了2个0,变成8比特位,对应1字节。这里正好多了三分之一,所以正常情况下,Base64编码的数据体积通常比原数据的体积大三分之一

  • 等号=
    3个英文字符,正好能转成4个Base64字符。那如果字符长度不是3的倍数,那应该使用什么样的规则呢?
    其实也简单,我们在实际使用Base编码时,常会发现有第65个字符的存在,那就是 = 符号,这个等于号就是针对这种特殊情况的一种处理方式。
    对于不足3个字节的地方,实际都会在后面补0,直到有24个二进制位为止。

    但要注意的是,在计算字节数时,会直接使用总长度除以3,如果余数为1则会直接在最后补一个=,如果余数为2则补两个=。因此,转码后的字符串需要补的后缀等号,要么是1个,要么是2个

    在这里插入图片描述
    图中第二个,使用的是单独的字符 d,是为了区分索引字符表里的索引0,这个时候,得到编码中,会存在一个索引0对应的A字符,而=是直接补上2个。

四、非ASCII码字符

由于 Base64 仅可对 ASCII 字符进行编码,如果是中文字符等非ASCII码,就需要先将中文字符转换为ASCII字符后,再进行编码才行

五、编解码方法

  • btoa 和 atob

    JavaScript提供了两个原生方法,用来处理Base64编码:btoa() 和 atob()。

    btoa(): 将字符串或二进制值转换成Base64编码字符串。

    注意:btoa方法只能直接处理ASCII码的字符,对于非ASCII码的字符,则会报错。

    atob(): 对base64 编码的字符串进行解码。

    注意:atob方法如果传入字符串参数不是有效的Base64编码(如非ASCII码字符),或者其长度不是4的倍数,会报错。

    btoa('you') // 'eW91'
    atob('eW91') // 'you'
    
    btoa('中') // Uncaught DOMException: The string to be encoded contains characters outside of the Latin1 range.
    atob('y') // Uncaught DOMException: The string to be decoded is not correctly encoded.
    
  • 处理中文字符

    由于btoa、atob 仅支持对ASCII字符编码,也就是单字节字符,而我们平时的中文都是 2-4 字节的字符。
    因此,可以先将中文字符转为utf-8的编码,将utf-8编码当做字符,这样就可以对多个单字节字符进行编码。

    对于中文可以使用这两个方法: encodeURIComponent()decodeURIComponent()

    encodeURIComponent():将非ACSII码的字符进行utf-8编码
    decodeURIComponent():解码使用

    如下,编解码中文的方式:

    window.btoa(encodeURIComponent('中国'))
    // 'JUU0JUI4JUFEJUU1JTlCJUJE'
    decodeURIComponent(window.atob('JUU0JUI4JUFEJUU1JTlCJUJE'))
    // '中国'
    
  • 第三方库 - js-base64

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值