当前位置: 首页 > 面试题库 >

使用Javascript的atob解码base64不能正确解码utf-8字符串

魏俊茂
2023-03-14
问题内容

我正在使用Javascript window.atob()函数解码base64编码的字符串(特别是来自GitHubAPI的base64编码的内容)。问题是我回来了ASCII编码的字符(â¢而不是)。如何正确处理传入的以base64编码的流,以便将其解码为utf-8?


问题答案:

此问题:

“ Unicode问题”由于DOMStrings是16位编码的字符串,因此在大多数浏览器中window.btoaCharacter Out Of Range exception如果字符超出8位字节的范围(0x00〜0xFF),则调用Unicode字符串将导致。有两种方法可以解决此问题:

* 第一个是转义整个字符串使用UTF-8,请参见encodeURIComponent,然后对其进行编码;
* 第二个是将UTF-16 DOMString转换为UTF-8字符数组,然后对其进行编码。

关于以前的解决方案的说明:MDN文章最初建议使用unescapeescape解决Character Out Of Range异常问题,但是自那以后就不建议使用。这里的其他一些答案建议使用decodeURIComponent和解决此问题,encodeURIComponent事实证明这是不可靠且不可预测的。此答案的最新更新使用现代JavaScript函数来提高速度和代码现代化。

编码UTF8⇢base64

function b64EncodeUnicode(str) {
    // first we use encodeURIComponent to get percent-encoded UTF-8,
    // then we convert the percent encodings into raw bytes which
    // can be fed into btoa.
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
        function toSolidBytes(match, p1) {
            return String.fromCharCode('0x' + p1);
    }));
}

b64EncodeUnicode('✓ à la mode'); // "4pyTIMOgIGxhIG1vZGU="
b64EncodeUnicode('\n'); // "Cg=="

解码base64⇢UTF8

function b64DecodeUnicode(str) {
    // Going backwards: from bytestream, to percent-encoding, to original string.
    return decodeURIComponent(atob(str).split('').map(function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
}

b64DecodeUnicode('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"
b64DecodeUnicode('Cg=='); // "\n"

2018年之前的解决方案(功能齐全,虽然可能会更好地支持旧版浏览器,但不是最新的)

这是直接来自MDN的当前建议,并通过@ MA-Maddin具有一些其他TypeScript兼容性:

// Encoding UTF8 ⇢ base64

function b64EncodeUnicode(str) {
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
        return String.fromCharCode(parseInt(p1, 16))
    }))
}

b64EncodeUnicode('✓ à la mode') // "4pyTIMOgIGxhIG1vZGU="
b64EncodeUnicode('\n') // "Cg=="

// Decoding base64 ⇢ UTF8

function b64DecodeUnicode(str) {
    return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
    }).join(''))
}

b64DecodeUnicode('4pyTIMOgIGxhIG1vZGU=') // "✓ à la mode"
b64DecodeUnicode('Cg==') // "\n"

原始解决方案(已弃用)

使用了escapeunescape(现在已弃用,尽管在所有现代浏览器中仍然可以使用):

function utf8_to_b64( str ) {
    return window.btoa(unescape(encodeURIComponent( str )));
}

function b64_to_utf8( str ) {
    return decodeURIComponent(escape(window.atob( str )));
}

// Usage:
utf8_to_b64('✓ à la mode'); // "4pyTIMOgIGxhIG1vZGU="
b64_to_utf8('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"

最后一件事:我在调用GitHubAPI时首先遇到了这个问题。为了使此功能在(Mobile)Safari上正常工作,实际上我什至必须解码base64源中的所有空白,然后才能对其进行解码。在2017年这是否仍然有意义,我不知道:

function b64_to_utf8( str ) {
    str = str.replace(/\s/g, '');    
    return decodeURIComponent(escape(window.atob( str )));
}


 类似资料:
  • 我正在使用Javascript函数来解码一个base64编码的字符串(特别是GitHub API中base64编码的内容)。问题是我得到了ASCII编码的字符(像而不是)。如何正确处理传入的base64编码的流,以便将其解码为UTF-8?

  • 我正在接收一个zip文件的内容(从一个API)作为一个base64编码的字符串。 如果我将该字符串粘贴到Notepad++中并执行 插件>MIME工具>Base64解码 生成类似的内容,但某些字符的解码方式不同(因此成为无效的zip文件)。其他方法抛出无效的URI错误。 如何在JavaScript中再现Notepad++行为?

  • 问题内容: 如何使用Android解码utf-8字符串?我尝试使用此命令,但输出与输入相同: 问题答案: 字符串不需要编码。它只是一个Unicode字符序列。 要将字符串转换为字节序列时需要进行 编码 。您选择的字符集(UTF-8,cp1255等)确定了Character-> Byte映射。请注意,字符不必转换为单个字节。在大多数字符集中,大多数Unicode字符都转换为至少两个字节。 字符串的编

  • 问题内容: 我在AngularJS上建立的SPA中有一个文本输入框,供用户向打印输出中添加标题。输入框的声明如下: 文本框中填充了服务器提供的默认标题。用户可以将标题更改为适合他们的名称。更改标题后,服务器将更新并在响应的标题中发送回新标题,然后替换框中的标题。这非常适合标准ASCII类型的字符。 但是,对于unicode字符(例如àßéçøö),它不起作用。文本已正确发送,在服务器上正确更新并正

  • 我需要解码成PDF文件的Base64字符串。我使用这个代码。但是window.atob命令总是报告错误:在窗口上执行“atob”失败:要解码的字符串没有正确编码。 我知道该文件是正确的,因为我已经使用一个将base64解码为pdf的网站对其进行了解码。我不知道它是否有用,但我们正在使用Aurelia框架。 转换函数 函数的调用

  • 问题内容: 我正在运行一个Python程序,该程序可获取UTF-8编码的网页,并使用BeautifulSoup从HTML中提取一些文本。 但是,当我将此文本写入文件(或在控制台上打印)时,它会以意外的编码方式写入。 示例程序: 运行此结果: 但是我希望Python Unicode字符串在单词中呈现为: 我已经试过了“fromEncoding”参数传递给BeautifulSoup,并试图与该对象,但