以下内容摘录,小编仅根据我处理问题时的流程进行了梳理
作者:JSON_NULL
链接:https://www.jianshu.com/p/b2c6dc5fad0a
使用浏览器下原生的 JavaScript 方法(btoa
和atob
)已经完全可以做到对字符串和二进制数据进行Base64的编码与解码;
原理是因为给 btoa
传递一个中文字符串作为参数时,会出现如下代码段所示的错误。
Uncaught DOMException: Failed to execute
'btoa' on 'Window': The string to be encoded
contains characters outside of the Latin1 range.
为什么会报错呢?
The string to be encoded contains characters outside of the Latin1 range.
被编码的字符串包含Latin1范围以外的字符。
Latin1 是什么东西?
ISO/IEC8859-1,又称Latin-1或“西欧语言”,是国际标准化组织内ISO/IEC 8859的第一个8位字符集。以ASCII为基础,在空置的0xA0-0xFF的范围内,加入96个字母及符号,藉以供使用变音符号的拉丁字母语言使用。
看明白了吧,其实btoa
只能转换占一个字节宽度的字符,就是Latin1字符集(它是ASCII的超集)。而中文汉字是被编码成占两个或以上个字节的。所以btoa
方法无法对中文进行操作,于是就报了上面看到的错误。
解决:
如:
btoa("橙-极纪元JJY.Cheng");
报错
Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.
编码 后再处理
btoa(unescape(encodeURIComponent("橙-极纪元JJY.Cheng")));
btoa(unescape(encodeURIComponent("橙-极纪元JJY.Cheng")));
//结果
'5qmZLeaegee6quWFg0pKWS5DaGVuZw=='
解码
decodeURIComponent(escape(atob('5oiR5piv5Lu15aOr5p2w')))
decodeURIComponent(escape(atob('5qmZLeaegee6quWFg0pKWS5DaGVuZw==')))
//结果
'橙-极纪元JJY.Cheng'
我们可以简单封装下
!function(W){
W.Base64 = {
utf8ToBase64:function (str){
return btoa(unescape(encodeURIComponent(str)));
},
base64ToUtf8: function(str){
return decodeURIComponent(escape(atob(str)));
}
}
}(window);
调用
Base64.utf8ToBase64('橙-极纪元JJY.Cheng')
'5qmZLeaegee6quWFg0pKWS5DaGVuZw=='
Base64.base64ToUtf8('5qmZLeaegee6quWFg0pKWS5DaGVuZw==')
'橙-极纪元JJY.Cheng'
那么问题来了!!!
为什么中文字符串转码后,就可以解决报错?
你可以看这篇文章
看完后,可以看下面内容
综合上面文章所述,我们可以清楚的知道,
encodeURI 和 encodeURIComponent 会把汉字等转换成UTF-8编码后对每个字节进行转义得到类似"%XX"(XX是两位十六进制值)的串。
而unescape 可以把所有 "%XX"(XX是两位十六进制值)的串,
解码到Latin1字符集上。
btoa 方法正好能够操作Latin1字符集上的字符转换成Base64编码。
于是乎以下代码段产生了:
function utf8ToBase64(str){
return btoa(unescape(encodeURIComponent(str)));
}
而解码过程是编辑过程的逆过程,于是得到如下代码
function base64ToUtf8(str){
return decodeURIComponent(escape(atob(str)));
}