由于浏览器内置的函数:btoa不支持多字节编码:
btoa("一")
执行会报错:Uncaught DOMException: Failed to execute 'btoa' on 'Window':
The string to be encoded contains characters outside of the Latin1 range.
mdn上给出的一种编码方案是:
window.btoa(unescape(encodeURIComponent('一'))) // 5LiA
然后反过来操作就是解码:
decodeURIComponent(escape(window.atob(str))) // 一
原理其实很简单:得到多字节字符的utf-8
编码,然后每个字节转成ascii字符,然后再用btoa
进行编码。
但是,escape
与unescape
都属于被废弃的函数,我们可以通过简单的转换来实现同样的功能:
function b64encode(str){
// 得到utf-8编码
const utf8 = encodeURIComponent(str)
// %xx对应的每字节转换成字符串
const utf8Str = utf8.replace(/%(\w{2})/g,(m,a)=>String.fromCharCode('0x' + a))
return btoa(utf8Str)
}
function b64decode(str){
// 每个字节处理成%xx形式
const utf8 = [...atob(str)].map(item => '%' + item.charCodeAt(0).toString(16)).join('')
// 解码utf8
return decodeURIComponent(utf8)
}