javascript - 将文件从插件复制到配置文件文件夹

标签 javascript firefox firefox-addon firefox-addon-sdk

我正在尝试将一个 sqlite 数据库从我的扩展目录中的数据文件夹复制到配置文件文件夹,以便使用它。

所以现在,我正在尝试:

const {Cc, Ci, Cu} = require("chrome");
const {NetUtils} = Cu.import("resource://gre/modules/NetUtil.jsm");
const data = require('sdk/self').data;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");

var file = Cc["@mozilla.org/file/directory_service;1"].
       getService(Ci.nsIProperties).
       get("TmpD", Ci.nsIFile);
file.append("searchEngines.sqlite");
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);

// Then, we need an output stream to our output file.
var ostream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
ostream.init(file, -1, -1, 0);

// Finally, we need an input stream to take data from.
var iStreamData = NetUtil.ioService.newChannel(data.url("searchEngines.sqlite"), null, null).open();
let istream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
istream.setData(iStreamData, iStreamData.length);

NetUtil.asyncCopy(istream, ostream, function(aResult) {
  console.log(aResult); // return 0
})

console.log(FileUtils.getFile("ProfD", ["searchEngines.sqlite"]).exists()); // return false

let dbConn = Services.storage.openDatabase(file);

该文件似乎存在,因为 console.log(file.exists()) 返回 FALSE 并且未填充(console.log(aResult) 返回 0 ).

我的错误在哪里,是否有更好的方法来做到这一点?

最佳答案

除了它使用同步 I/O(使用 .open 而不是 .asyncOpen 打开 channel ),NetUtil.asyncCopy 操作仍然是异步的,这意味着代码

NetUtil.asyncCopy(istream, ostream, function(aResult) {
  console.log(aResult); // return 0
})

console.log(FileUtils.getFile("ProfD", ["searchEngines.sqlite"]).exists()); // return false

let dbConn = Services.storage.openDatabase(file);

将尝试在复制可能完成之前打开文件! 但是,file.exists() 很可能为真,因为您已经打开文件进行写入。只是文件仍然是空白的,因为数据复制还没有完成(甚至还没有开始)。 (实际上,这是真的,因为您正在检查 ProfD 而不是 TmpD 中的 searchEngines.sqlite,但是如果您更正了前面的陈述会适用)。

您只能在回调 .asyncCopy 完成时/之后使用该文件,例如

NetUtil.asyncCopy(istream, ostream, function(aResult) {
  console.log(aResult);
  console.log(FileUtils.getFile("ProfD", ["searchEngines.sqlite"]).exists()); // return false
  let dbConn = Services.storage.openDatabase(file);
  // ...
});

PS:您可能想要.asyncOpen channel ,然后使用NetUtil.asyncFetch 并将生成的流传递给.asyncCopy对于小文件真正异步,因为它首先将内容缓存在内存中。

对于大文件,您可以创建 NetUtil.asyncFetch 实现的变体,将 .outputStream 端直接提供给 NetUtils.asyncCopy。这有点复杂,所以在有人真正对此感兴趣并提出相应问题之前,我不会详细写出来。

编辑,所以我会这样写:

const data = require('sdk/self').data;

Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");

function copyDataURLToFile(url, file, callback) {
  NetUtil.asyncFetch(url, function(istream) {
    var ostream = Cc["@mozilla.org/network/file-output-stream;1"].
                  createInstance(Ci.nsIFileOutputStream);
    ostream.init(file, -1, -1, Ci.nsIFileOutputStream.DEFER_OPEN);
    NetUtil.asyncCopy(istream, ostream, function(result) {
      callback && callback(file, result);
    });
  });
}

var file = Services.dirsvc.get("TmpD", Ci.nsIFile);
file.append("searchEngines.sqlite");
copyDataURLToFile(data.url("searchEngine.sqlite"), file, function(file, result) {
  console.log(result);
  console.log(file.exists());
  console.log(file.fileSize);
});

关于javascript - 将文件从插件复制到配置文件文件夹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24850460/

相关文章:

javascript - 防止径向渐变改变形状和大小

html - “Like” 页面被截断时的 Facebook 共享窗口

javascript - 如何监听 XMLHttpRequests - 浏览器扩展

javascript - 允许内容文档(网页)检测我的 Firefox 插件

javascript - 如何使用 .map() 将 promise 的结果分配给数组元素?

php - "pushing"数据库更改为网页未刷新

javascript - Firefox 在 append 内容时会扩展选择大小

firefox-addon - Firefox和质量检查测试工具?

javascript - Nodejs 重构 if 条件函数

将 POST 请求转换为 GET 的 Firefox 插件?