根据我的测试,标题中的错误只在谷歌Chrome中抛出。我正在base64编码一个大的XML文件,以便它可以下载:
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+">");
这一点。加载器是隐藏的iframe。
这个错误实际上是一个相当大的变化,因为通常情况下,谷歌Chrome浏览器会崩溃在btoa调用。Mozilla Firefox在这里没有问题,所以这个问题与浏览器有关。
我不知道档案里有什么奇怪的字。事实上,我相信没有非ascii字符。
问:
我如何找到有问题的字符,并替换他们,让Chrome停止抱怨?
我已经尝试使用downadify来启动下载,但它不起作用。它是不可靠的,并且不会抛出任何错误来进行调试。
我自己也遇到了这个问题。
首先,稍微修改你的代码:
var download = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+"<"+this.gamesave.tagName+">"
+this.xml.firstChild.innerHTML
+"</"+this.gamesave.tagName+">";
this.loader.src = "data:application/x-forcedownload;base64,"+
btoa(download);
然后使用你最喜欢的web检查器,在指定this.loader的代码行上放置一个断点。Src,然后执行以下代码:
for (var i = 0; i < download.length; i++) {
if (download[i].charCodeAt(0) > 255) {
console.warn('found character ' + download[i].charCodeAt(0) + ' "' + download[i] + '" at position ' + i);
}
}
根据应用程序的不同,替换超出范围的字符可能有效,也可能无效,因为您将修改数据。请参阅MDN上关于使用btoa方法使用unicode字符的说明:
https://developer.mozilla.org/en-US/docs/Web/API/window.btoa
我只是觉得我应该分享我是如何解决这个问题的,以及为什么我认为这是正确的解决方案(前提是你不针对旧浏览器进行优化)。
将数据转换为dataURL (data:…)
var blob = new Blob(
// I'm using page innerHTML as data
// note that you can use the array
// to concatenate many long strings EFFICIENTLY
[document.body.innerHTML],
// Mime type is important for data url
{type : 'text/html'}
);
// This FileReader works asynchronously, so it doesn't lag
// the web application
var a = new FileReader();
a.onload = function(e) {
// Capture result here
console.log(e.target.result);
};
a.readAsDataURL(blob);
允许用户保存数据
除了显而易见的解决方案-打开新窗口,以您的dataURL作为URL,您还可以做其他两件事。
1. 使用fileSaver.js
文件保护程序可以使用预定义的文件名创建实际的文件保存对话框。它还可以退回到正常的dataURL方法。
2. 使用(实验性)URL.createObjectURL
这对于重用base64编码的数据非常有用。它为你的dataURL创建一个简短的URL:
console.log(URL.createObjectURL(blob));
//Prints: blob:http://stackoverflow.com/7c18953f-f5f8-41d2-abf5-e9cbced9bc42
不要忘记使用包含前导blob前缀的URL。我使用文档。身体:
你可以使用这个短URL作为AJAX目标,<脚本>源或< > href位置。你要负责破坏URL:
URL.revokeObjectURL('blob:http://stackoverflow.com/7c18953f-f5f8-41d2-abf5-e9cbced9bc42')
将字符串转换为utf-8的解决方案,这比许多其他答案建议的utf-16或URLEncoded版本略短。它也与其他语言(如python和PHP)解码字符串的方式更加兼容:
编码
function btoa_utf8(value) {
return btoa(
String.fromCharCode(
...new TextEncoder('utf-8')
.encode(hash_value)
)
);
}
解码
function atob_utf8(value) {
const value_latin1 = atob(value);
return new TextDecoder('utf-8').decode(
Uint8Array.from(
{ length: value_latin1.length },
(element, index) => value_latin1.charCodeAt(index)
)
)
}
如果您愿意,您可以使用不同的字符编码替换其中的'utf-8'字符串。
注意:这取决于TextEncoder类。目前大多数浏览器都支持这一功能,但如果您需要针对较老的浏览器,请检查它是否可用。