Javascript 将数据URI写入Firefox扩展名中的文件
我正在开发一个Firefox插件。我需要将一组数据URI映像保存到磁盘。我该如何处理这个问题 我浏览了一遍,但这些片段对我帮助不大 有异步方法和同步方法。我想使用异步方法,但如何使用异步方法编写二进制文件Javascript 将数据URI写入Firefox扩展名中的文件,javascript,firefox,firefox-addon,Javascript,Firefox,Firefox Addon,我正在开发一个Firefox插件。我需要将一组数据URI映像保存到磁盘。我该如何处理这个问题 我浏览了一遍,但这些片段对我帮助不大 有异步方法和同步方法。我想使用异步方法,但如何使用异步方法编写二进制文件 Components.utils.import("resource://gre/modules/NetUtil.jsm"); Components.utils.import("resource://gre/modules/FileUtils.jsm"); // file is nsIFile
Components.utils.import("resource://gre/modules/NetUtil.jsm");
Components.utils.import("resource://gre/modules/FileUtils.jsm");
// file is nsIFile
var file = FileUtils.getFile("Desk", ["test.png"]);
// You can also optionally pass a flags parameter here. It defaults to
// FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE;
var ostream = FileUtils.openSafeFileOutputStream(file);
//base64 image that needs to be saved
image ="iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
// How can I create an inputstream from the image data URI?
var inputstream = createInputstream(image);
// The last argument (the callback) is optional.
NetUtil.asyncCopy(inputstream , ostream, function(status) {
if (!Components.isSuccessCode(status)) {
// Handle error!
return;
}
// Data has been written to the file.
});
听起来你不想写数据URI,而是想写它“包含”的二进制数据,所以我来回答这个问题
首先,假设我们得到了一些实际的数据URI(如果没有,添加data:application/octet-stream;base64,
并不难;)
选项1-使用OS.File
OS.File
具有真正异步的优点。另一方面,NetUtil
主要是异步的,因为在主线程上会有stat
调用,并且文件也会在主线程上打开并可能关闭(这可能导致缓冲区刷新,因此在刷新发生时阻塞主线程)
After(在某些常量的帮助下)适合该工作
Components.utils.import("resource://gre/modules/osfile.jsm");
var file = OS.Path.join(OS.Constants.Path.desktopDir, "test.png");
var str = imageDataURI.replace(/^.*?;base64,/, "");
// Decode to a byte string
str = atob(str);
// Decode to an Uint8Array, because OS.File.writeAtomic expects an ArrayBuffer(View).
var data = new Uint8Array(str.length);
for (var i = 0, e = str.length; i < e; ++i) {
data[i] = str.charCodeAt(i);
}
// To support Firefox 24 and earlier, you'll need to provide a tmpPath. See MDN.
// There is in my opinion no need to support these, as they are end-of-life and
// contain known security issues. Let's not encourage users. ;)
var promised = OS.File.writeAtomic(file, data);
promised.then(
function() {
// Success!
},
function(ex) {
// Failed. Error information in ex
}
);
你想写实际的,仍然编码的数据URI,还是它解码到的二进制数据?嘿@nMail你有什么文章我能读到关于数据URI编码到的
二进制数据的意思吗?@Noitidart Thx for Second soln我很想看看人们会怎么做,我会做不同的事情。在我的解决方案中,我使用了编码:'utf-8'
,所以我不需要//解码到Uint8Array
对吗?@Noitidart。不,事实上,我们的解决方案完全不同。我的先对数据URI中的base64编码数据进行解码,而你的则未经修改地写入。我不确定询问者想要什么,所以我想我可以提供一个替代方案。是的,你猜对了,写吧。。谢谢你的详细回答:)顺便说一句,我不明白为什么firefox会这么复杂。对于php,我可以只做文件内容('test.png',base64解码($base64String))啊,我知道了,它获取数据URI并将它们保存为磁盘上的png文件。很酷的东西。thx伙计们,通过charCodeAt将字符串转换为Uint8Array非常慢。相反,我们可以使用解码的字符串生成一个nsIStringInputStream
,将其设置为nsIBinaryInputStream
,readByteArray()
的输入流,并将其传递给Uint8Array
构造函数。更详细的代码,但转换速度也要快4-5倍(对于大字符串非常明显)。
Components.utils.import("resource://gre/modules/osfile.jsm");
var file = OS.Path.join(OS.Constants.Path.desktopDir, "test.png");
var str = imageDataURI.replace(/^.*?;base64,/, "");
// Decode to a byte string
str = atob(str);
// Decode to an Uint8Array, because OS.File.writeAtomic expects an ArrayBuffer(View).
var data = new Uint8Array(str.length);
for (var i = 0, e = str.length; i < e; ++i) {
data[i] = str.charCodeAt(i);
}
// To support Firefox 24 and earlier, you'll need to provide a tmpPath. See MDN.
// There is in my opinion no need to support these, as they are end-of-life and
// contain known security issues. Let's not encourage users. ;)
var promised = OS.File.writeAtomic(file, data);
promised.then(
function() {
// Success!
},
function(ex) {
// Failed. Error information in ex
}
);
Components.utils.import("resource://gre/modules/NetUtil.jsm");
Components.utils.import("resource://gre/modules/FileUtils.jsm");
// file is nsIFile
var file = FileUtils.getFile("Desk", ["test.png"]);
NetUtil.asyncFetch(imageDataURI, function(inputstream, status) {
if (!inputstream || !Components.isSuccessCode(status)) {
// Failed to read data URI.
// Handle error!
return;
}
// You can also optionally pass a flags parameter here. It defaults to
// FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE;
var ostream = FileUtils.openSafeFileOutputStream(file);
// The last argument (the callback) is optional.
NetUtil.asyncCopy(inputstream , ostream, function(status) {
if (!Components.isSuccessCode(status)) {
// Handle error!
return;
}
// Data has been written to the file.
});
});