根据我的测试,标题中的错误只在Google Chrome中出现。我正在对一个大的XML文件进行base64编码,以便下载:
this.loader.src = "data:application/x-forcedownload;base64,"+
btoa("<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+"<"+this.gamesave.tagName+">"
+this.xml.firstChild.innerHTML
+"</"+this.gamesave.tagName+">");
this.loader
是隐藏iframe。
这个错误实际上是一个很大的变化,因为通常情况下,谷歌Chrome会崩溃的btoa
调用。Mozilla Firefox没有问题,所以这个问题是浏览器相关的。我不知道任何奇怪的字符在文件中。实际上,我相信没有非ASCII字符。
**问:**如何找到有问题的字符并替换它们,以便Chrome不再抱怨?
我试过使用Downloadify来启动下载,但是它不起作用。它不可靠,并且不会抛出错误来允许调试。
8条答案
按热度按时间ygya80vv1#
如果您有UTF8,请使用以下代码(实际上可用于SVG源代码),例如:
例如:
如果需要解码base64,请使用以下代码:
示例:
**注意:**如果您需要在移动Safari中使用此功能,您可能需要从base64数据中剥离所有空白...
2017年更新
这个问题又一直困扰着我。
简单的事实是,atob并不真正处理UTF8字符串-它只处理ASCII字符串。
此外,我不会使用像js-base64这样的膨胀软件。
但是webtoolkit确实有一个小的、好的和非常可维护的实现:
https://www.fileformat.info/info/unicode/utf8.htm
rslzwgfq2#
改用程式库
我们不需要重新发明轮子。只要使用图书馆就可以保存时间和头痛。
js-base64版本
https://github.com/dankogai/js-base64很好,我确认它非常好地支持unicode。
g6baxovj3#
将
btoa
与unescape
和encodeURIComponent
一起使用对我来说不起作用。用XML/HTML实体替换所有特殊字符,然后转换为base64表示是解决这个问题的唯一方法。一些代码:z4bn682m4#
我只是觉得我应该分享一下我是如何解决这个问题的,以及为什么我认为这是正确的解决方案(前提是你不为旧浏览器优化)。
正在将数据转换为dataURL(
data: ...
)允许用户保存数据
除了用dataURL作为URL打开新窗口这一显而易见的解决方案之外,您还可以做另外两件事。
1.使用fileSaver.js
文件保存器可以创建实际的文件保存对话框与预定义的文件名。它也可以回退到正常的dataURL方法。
2.使用(实验)
URL.createObjectURL
这对于重用base64编码数据非常有用。它为您的dataURL创建一个短URL:
不要忘记使用包含前导
blob
前缀的URL。我再次使用了document.body
:您可以使用这个简短的URL作为 AJAX 目标、
<script>
源或<a>
href位置。ghhkc1vu5#
作为对Stefan Steiger回答的补充:(因为作为评论看起来不太好)
扩展字符串原型:
用法:
注意事项:
如注解中所述,不建议使用
unescape
,因为将来可能会删除它:警告:虽然unescape()并没有被严格地弃用(如“从Web标准中删除”),但它在ECMA-262标准的附录B中定义,其介绍如下:...... * 本附录中规定的所有语言特性和行为都有一个或多个不良特征,如果没有遗留用法,将从本规范中删除。*
注意:请勿使用unescape来编码URI,请改用decodeURI或decodeURIComponent。
jtw3ybtb6#
btoa()仅支持从String.fromCodePoint(0)到String.fromCodePoint(255)的字符。对于代码点为256或更高的Base64字符,您需要在前后对这些字符进行编码/解码。
在这一点上,它变得棘手...
每个可能的符号都排列在一个Unicode表中。Unicode表被划分在不同的平面(语言、数学符号等)中。平面中的每个符号都有一个唯一的代码点编号。理论上,该编号可以变得任意大。
计算机以字节为单位存储数据(8位,十六进制0x 00 - 0xff,二进制0000000 - 1111111,十进制0 - 255)。此范围通常用于保存基本字符(Latin 1范围)。
对于代码点大于255的字符,存在不同的编码。JavaScript使用每个符号16位(UTF-16),称为DOMString的字符串。Unicode可以处理代码点高达0x 10 fffff。这意味着,必须存在一个方法来存储几个单元格中的几位。
String.fromCodePoint(0x10000).length == 2
UTF-16使用代理对在两个16位单元中存储20位。第一个较高的代理以110110 xxxxxxxxxx开头,第二个较低的代理以110111 xxxxxxxxxx开头。Unicode为此保留了自己的平面:https://unicode-table.com/de/#high-surrogates
要以字节(Latin 1范围)存储字符,标准化过程使用UTF-8。
很抱歉这么说,但我认为没有其他方法来实现这个函数self。
使用方法:
decodeBase64(encodeBase64("\u{1F604}"))
演示:https://jsfiddle.net/qrLadeb8/
ryoqjall7#
我自己也遇到了这个问题。
首先,稍微修改代码:
然后使用您喜欢的Web检查器,在指定此.loader.src的代码行上放置断点,然后执行以下代码:
根据您的应用程序,替换超出范围的字符可能有效,也可能无效,因为您将修改数据。请参阅MDN上关于使用btoa方法替换unicode字符的注解:
https://developer.mozilla.org/en-US/docs/Web/API/window.btoa
ecfdbz9o8#
另一种不使用
unescape
的浏览器解决方案: