我正在按照下面的代码将字符串转换为BASE64...
var str = "Hello World";
var enc = window.btoa(str);
这将产生SGVsbG8gV29ybGQ=
。但是如果我添加这些字符– ”
,如下所示的代码,则不会发生转换。这背后的原因是什么?非常感谢。
var str = "Hello – World”";
var enc = window.btoa(str);
我正在按照下面的代码将字符串转换为BASE64...
var str = "Hello World";
var enc = window.btoa(str);
这将产生SGVsbG8gV29ybGQ=
。但是如果我添加这些字符– ”
,如下所示的代码,则不会发生转换。这背后的原因是什么?非常感谢。
var str = "Hello – World”";
var enc = window.btoa(str);
btoa
是一种特殊的函数,它要求使用“二进制字符串”这种8位字符格式。它无法处理charcode值超过255的unicode值,例如您使用的em破折号和“花式”引号符号。
您可以将字符串转换为符合单字节打包的新字符串(然后手动重构相关atob
的结果),或者您可以先对数据进行URI编码,使其安全:
> var str = `Hello – World`;
> window.btoa(encodeURIComponent(str));
"SGVsbG8lMjAlRTIlODAlOTMlMjBXb3JsZA=="
在解包时,记得再次进行解码:
> var base64= "SGVsbG8lMjAlRTIlODAlOTMlMjBXb3JsZA==";
> decodeURIComponent(window.atob(base64));
"Hello – World"
btoa
接受字符串”和“将字符串数据编码为base64”不是相同的事情。 如果您只想传递字符串,那么这样做就可以了。 如果您想要实现从Unicode到Unicode的通用序列化/反序列化,则必须执行我没有提供代码的部分:将您的字符串展平为其字节码等效项。 然后,如果您需要自己解码它(而不是依赖于data-uri解码),则必须编写自己的“扁平字节到正确的Unicode”重建代码,并且在此时,您可能需要一个正确的base64库,而不是 btoa
。 - Mike 'Pomax' Kamermans”
超出了Latin1范围。unescape
(现已弃用)。
var str = "Hello – World”";
var enc = btoa(unescape(encodeURIComponent(str)));
alert(enc);
并且解码:
var encStr = "SGVsbG8g4oCTIFdvcmxk4oCd";
var dec = decodeURIComponent(escape(window.atob(encStr)))
alert(dec);
最可靠的方法是直接处理二进制数据。
为此,您可以将字符串编码为表示其UTF-8版本的ArrayBuffer
对象。
然后,FileReader
实例将能够轻松地为您提供base64。
var str = "Hello – World”";
var buf = new TextEncoder().encode( str );
var reader = new FileReader();
reader.onload = evt => { console.log( reader.result.split(',')[1] ); };
reader.readAsDataURL( new Blob([buf]) );
由于Blob()
构造函数自动将DOMString
实例编码为UTF-8,因此我们甚至可以摆脱TextEncoder
对象:
var str = "Hello – World”";
var reader = new FileReader();
reader.onload = evt => { console.log( reader.result.split(',')[1] ); };
reader.readAsDataURL( new Blob([str]) );
这最终归因于JavaScript类型系统的不足。
JavaScript字符串是由16位代码单元组成的,通常被解释为UTF-16。Base64编码是一种将8位字节流转换为数字串的方法,通过将每三个字节映射到四个数字,每个数字覆盖6位:3×8=4×6。正如我们所看到的,这在很大程度上取决于每个符号的位宽。
在定义btoa
函数时,JavaScript没有针对8位字节流的类型,因此API被定义为以普通的16位字符串类型作为输入,并限制每个代码单元应该被限制在[U+0000,U+00FF]范围内;当编码为ISO-8859-1时,这样的字符串将完全复制预期的字节流。
字符–
是U+2013,而”
是U+201D;这两个字符都不适合上述范围,因此该函数会拒绝它们。
如果你想将Unicode文本转换为Base64,你需要先选择一个字符编码并将其转换为字节字符串,然后对其进行编码。要求对Unicode字符串本身进行Base64编码是没有意义的。