这是我第一次尝试编写 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。
我不应该在附加组件的 main.js
中使用 OS.File
吗?
我应该使用FileUtils
,即Components.utils.import("resource://gre/modules/FileUtils.jsm");
吗?
最佳答案
首先,您链接了 Workers-docs 的 OS.File
。您不在工作线程中使用它(任何地方都没有 new Worker
),而是在主线程中使用它,因此您需要引用 OS.File
for the main thread -文档。
遗憾的是,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.File
、FileUtils
、sdk/io/...
不适合读取附加组件中的文件,因为通常这些文件不会直接位于用户的文件系统中,而是位于已安装的 XPI 文件(这只是一个 zip 文件)中,并且这些 API 允许您逐字读取文件,但不解析容器为您提供 .zip 文件 (XPI)。
不过,您有几个选择:
- 文件名似乎表明您想要本地化某些内容。 SDK 附带
l10n
module正是为了这个目的。 - 位于附加组件
data/
文件夹中的内容也可以使用self.data.load()
来读取,但您仍然需要解码/解析数据。 - 您可以使用
XMLHttpRequest
读取附加组件 (XPI) 中打包的文件,SDK 在net/xhr
中提供该功能。模块。作为额外的好处,您可以通过设置适当的.responseType
值让XHR
对象为您解码和/或解析文件。
如果要读取的文件位于插件的 data/
文件夹中,则构建 XHR
的 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
和一般的 Promise 时,请考虑使用 Task.jsm
这可以使编写和重新读取(维护)代码变得更加容易。
关于javascript - Firefox SDK 插件中的 OS.File,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24174046/