Firefox SDK附加组件中的OS.File

时间:2014-06-11 23:08:24

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

这是我第一次尝试编写Firefox附加组件。

我正在尝试阅读我正在撰写的Firefox附加组件中包含的文本文件。

我正在关注示例from MDN

let decoder = new TextDecoder();      // This decoder can be reused for several reads
let array = OS.File.read("file.txt"); // Read the complete file as an array
let text = decoder.decode(array);     // Convert this array to a text

在我的main.js中,我有以下代码段:

Components.utils.import("resource://gre/modules/osfile.jsm");

var pathFile = OS.Path.join("_locales", "en", "messages.json");        

let decoder = new TextDecoder('utf-8');

let promise = OS.File.read(pathFile);        
promise = promise.then(
  function onSuccess(array) {
    return decoder.decode(array);
  },
  function onReject(array) {
    console.log("onReject read: ");
  }            
);

当我使用cfx run命令运行加载项时,出现以下错误:

Message: ReferenceError: TextDecoder is not defined

我目前正在使用Firefox 30和Firefox Add-on SDK 1.16。

我是否应该在加载项OS.File中使用main.js

我应该使用FileUtils代替Components.utils.import("resource://gre/modules/FileUtils.jsm");吗?

2 个答案:

答案 0 :(得分:3)

首先,您为Workers-docs链接了OS.File。你不是在一个工人中使用它(在任何地方没有new Worker),而是主线程,所以你宁愿引用OS.File for the main thread - docs。

遗憾的是,SDK模块现在无法自动获取TextEncoder / TextDecoder。 正如@erikvold建议的那样,你可以:

const { Buffer, TextEncoder, TextDecoder } = require('sdk/io/buffer');

甚至直接从osfile.jsm获取:

const { Cc, Ci, Cu } = require("chrome");
const { OS, TextEncoder, TextDecoder } = Cu.import("resource://gre/modules/osfile.jsm", {});

现在回到原来的问题:

通常OS.File可以在SDK附加组件中使用,是在文件系统中读/写任意文件的好方法。

但是OS.FileFileUtilssdk/io/...不适合阅读附加组件中的文件,因为通常这些文件不会直接位于用户的文件系统中,而是位于已安装的XPI文件(仅仅是一个zip文件)中,这些API允许您逐字读取文件,但不要为您解析容器zip文件(XPI)。

但是你有几个选择:

  • 文件名似乎表示您想要本地化。完全为此目的提供了SDK l10n module
  • 也可以使用self.data.load()读取位于附加组件的data/文件夹中的内容,但仍需要解码/解析数据。
  • 您可以使用XMLHttpRequest读取加载项(XPI)中打包的文件,SDK可在net/xhr模块中使用该文件。作为额外的好处,您可以通过设置适当的XHR值让.responseType对象解码和/或解析文件。

如果要读取的文件位于附加组件的XHR文件夹中,则构造data/的URI很容易,例如

cont self = require("sdk/self");
var uri = self.data.url("en/messages.json");
// would map to data/en/messages.json

否则,实际上并没有一种获得URI的官方支持方式,例如以下内容适用于lib/(目前,但未来可能会失败)。

cont self = require("sdk/self");
var uri = self.data.url("../lib/main.js");
// would map to data/../lib/main.js -> lib/main.js

将您自己的文件放在其他地方很棘手,因为SDK只会在构建XPI时打包某些路径;一般来说lib/data/locale/(请参阅l10n),chrome/(请参阅XUL Migration Guide

以下是使用XHR的最小示例(但请记住,对于本地化,已经有l10n模块):

const self = require("sdk/self");
const { XMLHttpRequest } = require("sdk/net/xhr");

// Assume data/some.json is:
// {"abc":123}
var req = new XMLHttpRequest();
req.onload = function() {
  // req.response is an object containing the parsed JSON.
  console.log(req.response.abc); // 123
};
req.open("GET", self.data.url("some.json"));
req.responseType = "json";
req.send();

PS:特别是在使用OS.File和一般承诺时,请考虑使用Task.jsm,这样可以更容易地编写和重新读取(维护)代码。

答案 1 :(得分:2)

尝试

const { Buffer, TextEncoder, TextDecoder } = require('sdk/io/buffer');
const { OS } = require("resource://gre/modules/osfile.jsm");

var pathFile = OS.Path.join("_locales", "en", "messages.json");        

let decoder = new TextDecoder('utf-8');

let promise = OS.File.read(pathFile);        
promise = promise.then(function onSuccess(array) {
  return decoder.decode(array);
}, function onReject(array) {
  console.log("onReject read: ");
});