我叫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/

    10-09 20:13