此问题:
“ Unipre问题”由于
DOMStrings是16位编码的字符串,因此在大多数浏览器中
window.btoa,
Character Out Of Range exception如果字符超出8位字节的范围(0x00〜0xFF),则调用Unipre字符串将导致。有两种方法可以解决此问题:
* 第一个是转义整个字符串使用UTF-8,请参见
enpreURIComponent,然后对其进行编码;
* 第二个是将UTF-16
DOMString转换为UTF-8字符数组,然后对其进行编码。
关于以前的解决方案的说明:MDN文章最初建议使用unescape
和escape
解决Character Out OfRange
异常问题,但是自那以后就不建议使用。这里的其他一些答案建议使用depreURIComponent
和解决此问题,enpreURIComponent
事实证明这是不可靠且不可预测的。此答案的最新更新使用现代Javascript函数来提高速度和代码现代化。
编码UTF8⇢base64
function b64EnpreUnipre(str) { // first we use enpreURIComponent to get percent-enpred UTF-8, // then we convert the percent encodings into raw bytes which // can be fed into btoa. return btoa(enpreURIComponent(str).replace(/%([0-9A-F]{2})/g, function toSolidBytes(match, p1) { return String.fromCharCode('0x' + p1); }));}b64EnpreUnipre('✓ à la mode'); // "4pyTIMOgIGxhIG1vZGU="b64EnpreUnipre('n'); // "Cg=="解码base64⇢UTF8
function b64DepreUnipre(str) { // Going backwards: from bytestream, to percent-encoding, to original string. return depreURIComponent(atob(str).split('').map(function(c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join(''));}b64DepreUnipre('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"b64DepreUnipre('Cg=='); // "n"2018年之前的解决方案(功能齐全,虽然可能会更好地支持旧版浏览器,但不是最新的)
这是直接来自MDN的当前建议,并通过@ MA-Maddin具有一些其他Typescript兼容性:
// Encoding UTF8 ⇢ base64function b64EnpreUnipre(str) { return btoa(enpreURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) { return String.fromCharCode(parseInt(p1, 16)) }))}b64EnpreUnipre('✓ à la mode') // "4pyTIMOgIGxhIG1vZGU="b64EnpreUnipre('n') // "Cg=="// Decoding base64 ⇢ UTF8function b64DepreUnipre(str) { return depreURIComponent(Array.prototype.map.call(atob(str), function(c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2) }).join(''))}b64DepreUnipre('4pyTIMOgIGxhIG1vZGU=') // "✓ à la mode"b64DepreUnipre('Cg==') // "n"原始解决方案(已弃用)
使用了
escape和
unescape(现在已弃用,尽管在所有现代浏览器中仍然可以使用):
function utf8_to_b64( str ) { return window.btoa(unescape(enpreURIComponent( str )));}function b64_to_utf8( str ) { return depreURIComponent(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 depreURIComponent(escape(window.atob( str )));}


