Javascript 将数据URI写入Firefox扩展名中的文件

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

我正在开发一个Firefox插件。我需要将一组数据URI映像保存到磁盘。我该如何处理这个问题

我浏览了一遍,但这些片段对我帮助不大

有异步方法和同步方法。我想使用异步方法,但如何使用异步方法编写二进制文件

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.
  });
});