Firefox附加组件。如何真正下载图像/文件?

时间:2016-03-04 12:13:31

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

我越来越心灰意冷了。在过去的三天里,我一直在努力为我的简单的Firefox插件增加一个“下载图片”功能。

以下是一个附加组件,可创建带有子菜单的右键单击上下文菜单:

var contextMenu = require("sdk/context-menu");
var clipboard = require("sdk/clipboard");
var data = require("sdk/self").data;

var myApp_cm = contextMenu.Menu({
label:          "Send to myApp",
context:        contextMenu.SelectorContext("body"),
items: [

    contextMenu.Item({ 
        label:          "Send image to MyApp",
        context:        contextMenu.SelectorContext("img"),
        contentScript:  'self.on("click", function (node, data) { ' +
                        '  var link = node.src; ' +
                        '  self.postMessage(link); ' +
                        '});',
        onMessage:      function(link) {
                            //
                            // Download image from 'link' and run 'myApp.exe' with
                            // downloaded image as parameter
                            //
                        } 
        })
    ]
});

我想在上面的代码中添加一个简单的下载功能,作为Firefox 的“另存为...”选项,该选项从选定的URL下载图像并以下载的图像作为参数运行EXE

我阅读了从Mozilla MDN开始到Stackoverflow提出的所有问题的所有关于此论点的内容。但是,我从来没有设法使一行代码工作。我真的不明白为什么在这是浏览器的工作时下载文件这么复杂。

例如,我知道从Firefox 26+开始我需要使用 downloads.jsm 。所以,我从MDN复制了以下代码。

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

Task.spawn(function () {
    yield Downloads.fetch("http://www.mozilla.org/",OS.Path.join(OS.Constants.Path.tmpDir,"example-download.html"));
    console.log("example-download.html has been downloaded.");
}).then(null, Components.utils.reportError);

但是,我一直收到以下错误:

enter image description here

所以我添加了字符串let {Cu, Ci, CC} = require('chrome'),但没有任何变化。

我今年43岁,我还在学习JavaScript。我知道我没有20年前的灵活性。但是,我记得编程更加直截了当。我仍然喜欢编程,但现在我经常觉得很沮丧。

2 个答案:

答案 0 :(得分:2)

我实际上没有尝试过,但我不会指望destructuring assignment

let {Cu, Ci, Cc} = require('chrome');

[注意:您的CC应为Cc。]

提供您的附加SDK代码,以通过将其引用为Components来访问完整的Components对象,但仅限于您已分配给&的属性(子对象) #34;别名"通过使用let

定义的对象可用
Object ("alias") now available           Object full name normally available
to your SDK add-on                       to Overlay and Restartless add-ons
Cu                                =      Components.utils
Ci                                =      Components.interfaces
Cc                                =      Components.classes

解构赋值应该只提取Cu中称为CiCcrequre('chrome')的属性(子对象)。

您从MDN复制的代码需要更改为:

Cu.import("resource://gre/modules/Downloads.jsm");
Cu.import("resource://gre/modules/osfile.jsm")
Cu.import("resource://gre/modules/Task.jsm");

Task.spawn(function () {
    yield Downloads.fetch("http://www.mozilla.org/",
                          OS.Path.join(OS.Constants.Path.tmpDir,"example-download.html"));
    console.log("example-download.html has been downloaded.");
}).then(null, Cu.reportError);

如果您想在不使用ComponentsCcCiCuCr别名的情况下使用Cm,需要使用:

let {components} = require('chrome'); // note the lowercase "components"
let Components = components;

然后您可以使用原始代码:

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

Task.spawn(function () {
    yield Downloads.fetch("http://www.mozilla.org/",
                          OS.Path.join(OS.Constants.Path.tmpDir,"example-download.html"));
    console.log("example-download.html has been downloaded.");
}).then(null, Components.utils.reportError);

有关详细信息,您可以在MDN上看到Chrome Authority页面。

答案 1 :(得分:2)

  

所以,我从MDN复制了以下代码。

这是你问题的重要部分。你在没有推理的情况下复制代码。代码片段通常具有必须满足的先决条件和假设,即必须在特定上下文中评估它们 - 例如,npm模块不会在浏览器中运行。

这些代码段也具有依赖性,例如Components对象。错误消息会向您发出警告,因此阅读文档on require("chrome")Components可能是一个很好的提示。

第二个问题是您尝试在SDK插件中使用JSM而不首先查找等效的SDK API。请注意,顶级MDN Addon页面区分了几种类型的扩展,尤其是SDK和旧版扩展。您正在编写SDK扩展程序。

因此,为了下载图像而不是通过文件下载管理器(Downloads.jsm),您只需使用requestIO SDK模块下载文件,然后{{3生成exe。

Task.spawn(function () {
    yield Downloads.fetch("http://www.mozilla.org/",

那是在生成器函数之外使用yield,这是遗留语法,不应该使用。

对于链接,您可能应该使用ES6 child_process代替。