使用WebExtensions API处理下载的文件

时间:2016-08-17 12:17:03

标签: firefox firefox-addon firefox-webextensions

我想使用他们的WebExtensions API创建一个Firefox扩展。扩展名应查找与名称中的特定模式匹配的任何尝试下载的文件。如果扩展程序发现尝试下载的名称与该特定模式匹配,则会将下载内容放入另一个硬编码目录中。

看起来很简单。但是,在查看Firefox的WebExtensions API中的可用功能之后,我找不到任何可以轻松执行此操作的内容。以下是我看过的主要链接:

WebExtensions {➞{3}} {➞{3}}
JavaScript APIs {➞{3}} {➞{3}} {➞{3}}

似乎都不适合我正在寻找的东西。任何人都知道我怎么能做到这一点?

1 个答案:

答案 0 :(得分:1)

使用WebExtensions执行此操作的“正确”方式看起来并不是(但是?)Firefox支持。谷歌浏览器有'onDeterminingFilename'事件,允许您向用户“建议”文件名。如果在这种情况下需要,允许用户覆盖您的扩展名的“建议”可能会更好。

执行此操作的强力方法是向downloads.onCreated添加侦听器。该听众传递的是downloads.DownloadItem,它会为您提供urlfilename。然后,听众可以downloads.cancel()下载并使用您想要的filename发起一个新的downloads.download()

这在实际中如何工作取决于downloads.onCreated事件确实在与用户的交互方面实际触发的时间。是否在与用户“另存为”对话框之前或之后触发?您需要对此进行测试,以了解哪种方法最适合您希望用户拥有的感觉。 downloads.State类型可以包含的有限值集指示仅在“另存为”对话框完成后才触发事件,但这可能不是准确的指示。如果它在“另存为”对话框之前触发,我们可以通过将saveAs: true属性添加到我们传递给downloads.download()的对象

像(未经测试)的东西:

var ignoreDownloadUrls=[];
var ignoreDownloadIds=[];

chrome.downloads.onCreated.addlistener(forceDownloadFilenameIfUrlMatch);

function forceDownloadFilenameIfUrlMatch(downloadItem){
    //Check the URL for duplication (may not be needed, need to test).
    let foundUrlIndex = ignoreDownloadUrls.findIndex(function(element,index){
        if(element === downloadItem.url){
            return true;
        }//else
        return false;
    });
    if(foundUrlIndex>-1) {
        //This is the callback resulting from our creating the download
        //  with the new filename. We only want to ignore the URL once,
        //  so, remove the URL from our ignore list.
        //  This makes the assumption that the events we get are reasonably
        //  orderly (only one created event per URL which we want to
        //  change, etc.). This may need to be more complex in real use.
        ignoreDownloadUrls.splice(foundUrlIndex,1);
        //We do not want to change this download, as we created it.
        return;
    }
    //Test the ID for one we created:
    let foundIdIndex = ignoreDownloadIds.findIndex(function(element,index){
        if(element === downloadItem.id){
            return true;
        }//else
        return false;
    });
    if(foundIdIndex>-1) {
        //This is an event resulting from our creating the download
        //  with the new filename.
        //We do not want to change this download, as we created it.
        return;
    }
    if(downloadItem.url.idexOf(myMatchString) >-1){
        chrome.downloads.cancel(downloadItem.id);
        //Remember the URL so we don't change it twice.
        //  Remembering the URL may not be the best way to do this. Need
        //  to test as to the order which events and the download callback
        //  occur.
        ignoreDownloadUrls.push(download.url);
        chrome.downloads.download({
            url: downloadItem.url,
            filename: myNewFilename
        }, function(id){
        //We could use the callback of the downloads.download() to remember
        //  the downloadId of the download we created and only ignore that
        //  one.  That would rely on the callback being called prior to the
        //  new onCreated event. Might work that way in practice. It
        //  would certainly be better to remember the specifically created
        //  downloadId rather than just ignore (once) a specific URL.
        //  Testing should indicate if we need to use the download ID,
        //  or ignore the URL (once).
            //Remember the downloadId so we don't change it twice.
            ignoreDownloadIds.push(id);
        });
    }
}