我叫Festus。
我需要通过JavaScript在浏览器中将字符串与Base64相互转换。这个站点和Mozilla都很好地涵盖了该主题,建议的解决方案似乎遵循以下原则:
function toBase64(str) {
return window.btoa(unescape(encodeURIComponent(str)));
}
function fromBase64(str) {
return decodeURIComponent(escape(window.atob(str)));
}
我进行了更多研究,发现不推荐使用
escape()
和unescape()
,并且不应再使用它们。考虑到这一点,我尝试删除对不赞成使用的函数的调用,这将产生:function toBase64(str) {
return window.btoa(encodeURIComponent(str));
}
function fromBase64(str) {
return decodeURIComponent(window.atob(str));
}
这似乎可行,但提出了以下问题:
(1)为什么最初提出的解决方案包含对
escape()
和unescape()
的调用?该解决方案是在弃用之前提出的,但是大概这些功能在当时增加了某种值(value)。(2)在某些极端情况下,删除这些不赞成使用的调用会导致包装函数失败吗?
注意:关于String => Base64转换的问题,StackOverflow上还有其他更为冗长和复杂的解决方案。我确定它们可以正常工作,但是我的问题特别与此流行的解决方案有关。
谢谢,
节日
最佳答案
TL; DR原则上不需要escape()
/unescape()
,并且没有弃用功能的第二个版本是安全的,但它会生成更长的base64编码输出:
console.log(decodeURIComponent(atob(btoa(encodeURIComponent("€uro")))))
console.log(decodeURIComponent(escape(atob(btoa(unescape(encodeURIComponent("€uro")))))))
两者都创建了输出
"€uro"
,但没有使用更长的base64表示形式的escape()
/unescape()
版本btoa(encodeURIComponent("€uro")).length // = 16
btoa(unescape(encodeURIComponent("€uro"))).length // = 8
escape()
/unescape()
步骤仅在相应的情况下才需要(例如,不可调整的php-Script期望base64以特定方式完成)。长版:
首先,为了更好地理解您在上面建议的
toBase64()
和fromBase64()
的两个版本之间的差异,让我们看一下问题的核心btoa()
。文档说,btoa的命名是助记符,因此随着文档的不断增加,这在某种程度上具有误导性,
更加不完美的是,
btoa()
实际上仅接受显然,只有btoa()可以使用英语字母数字文本。
两种版本中都有的encodeURIComponent()的用途是帮助解决字符范围在U + 0000到U + 00FF之间的字符串。
一个示例是具有三个字符的字符串“uü€”
a
(U + 0061)ä
(U + 00E4)€
(U + 20AC)这里只有前两个字符在范围内。
第三个字符,欧元符号,在外面,并且
window.btoa("€")
引发超出范围的错误。为避免此类错误,需要一种解决方案,以在U + 0000到U + 00FF的集合中表示“€”。这是window.encodeURIComponent的作用:
window.encodeURIComponent("uü€")
创建以下字符串:"a%C3%A4%E2%82%AC"
其中一些字符已被编码a
= a
(保持不变)ä
= %C3%A4
(已更改为utf8表示形式)€
= %E2%82%AC
(已更改为utf8表示形式)(更改为utf8表示形式)通过使用字符“%”和字符的utf8表示形式的每个字节的两位数字来工作。 “%”是U + 0025,因此允许在
btoa()
-range内。的结果然后可以将
window.encodeURIComponent("uü€")
馈送到btoa()
,因为它不再具有超出范围的字符:btoa("a%C3%A4%E2%82%AC") \\ = "YSVDMyVBNCVFMiU4MiVBQw=="
在
unescape()
和btoa()
之间使用encodeURIComponent()
的症结在于,utf8表示形式的所有字节都使用最多3个字符的%xx
来存储字节0x00至0xFF的所有可能值。在这里unescape()
可以扮演的可选 Angular 色。这是因为unescape()
占用了所有这些%xx
字节,并在允许的U + 0000到0 + 00FF范围内创建了一个Unicode字符。去检查 :
btoa(encodeURIComponent("uü€"))).length // = 24
btoa(unescape(encodeURIComponent("uü€"))).length // = 8
主要区别在于减少了文本的base64表示形式的长度,但需要通过可选的
escape()
/unescape()
进行额外的解析,这在以ASCII字符集为主的情况下,无论如何都是最小的。要了解的主要类(class)是
btoa()
的名称具有误导性,并且需要encodeURIComponent()
本身生成的Unicode U + 0000至U + 00FF字符。不推荐使用的escape()
/unescape()
仅具有节省空间的功能,这可能是合乎需要的,但不是必需的。 Unicode符号> U + 00FF的问题在此处称为btoa/atob Unicode problem,它甚至提到了将“所有UTF8 Unicode”改进为现代浏览器中的base64编码的方法。关于javascript - 在不使用不推荐使用的 'Escape'调用的情况下,在JavaScript中转换为Base64,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30631927/