6

我试图在Chrome扩展中下载多个文件。以下代码创建一个到文件的虚拟链接,然后触发下载该文件的.click()事件。 问题是只有第一个.click()事件触发下载。后续的.click()事件被忽略。JavaScript click()方法只能在Chrome扩展中运行一次

这里manifest.json的

{ 
    "name": "Simple File Downloader", 
    "version": "0.1", 
    "permissions": ["contextMenus", "http://*/"], 
    "background": { 
    "persistent": false, 
    "scripts": ["sample.js"] 
    }, 
    "content_security_policy": "script-src 'self'; object-src 'self'", 
    "manifest_version": 2 
} 

这里sample.js

function onClickHandler(info, tab) { 
    var a = document.createElement('a'); 
    a.href = 'http://or.cdn.sstatic.net/chat/so.mp3'; 
    a.download = 'so.mp3'; 
    document.body.appendChild(a); 
    a.click(); // this click triggers the download 
    // this timeout violates content security policy 
    // setTimeout(a, 300); 
    a.click(); // this click doesn't do anything 
    document.body.removeChild(a); 

    a = document.createElement('a'); 
    a.href = 'http://or.cdn.sstatic.net/chat/so.mp3'; 
    a.download = 'so.mp3'; 
    document.body.appendChild(a); 
    a.click(); // this click doesn't do anything either 
    document.body.removeChild(a); 
}; 

chrome.contextMenus.onClicked.addListener(onClickHandler); 
chrome.runtime.onInstalled.addListener(function() { 
    chrome.contextMenus.create({"title": "Download File", "id":"download_file"}); 
}); 

我已经试过:

惊讶为什么很难简单地保存多个文件。感谢任何帮助。

+1

等了几个月,和['chrome.downloads'](https://developer.chrome.com/dev/extensions/downloads。HTML)API广泛可用。关于CSP错误:'a'是一个链接,其'toString'属性返回链接的目标。所以,如果你使用'setTimeout(a,300);',它会尝试评估链接的目标。字符串作为代码评估是默认禁止的,所以你会得到错误。但是,如果使用'setTimeout(function(){a.click();},300);',该文件仍然没有被下载。 –

+0

您是否找到解决此问题的临时解决方案? – coneybeare

+0

我认为这是不可能的安全问题。如果可能的话,那么事实上我可以打开无限弹出/下载只需点击一下。 –

回答

0

而不是使用.live()梅索德,因此不再建议尝试.on()

$(document).on("click", "a", function(event){ 
    // do whatever 
}); 

这里是documentation

+0

感谢您的提示,但不幸的是,这并没有帮助。 – toby88

4

的诀窍是不使用element.click方法,而是创建多个MouseEvent。为此,每次需要点击时,您都需要创建一个MouseEvent

function clicker(el, clickCount) { 
    var mousedownEvent; 
    while(clickCount--) { 
    mousedownEvent = document.createEvent("MouseEvent"); 
    mousedownEvent.initMouseEvent("click", true, true, window, 0, null, null, null, null, false , false, false, false, 0, null); 
    el.dispatchEvent(mousedownEvent); 
    } 
} 

clicker(a, 3); 
// your anchor 'a' gets clicked on 3 times. 

当使用Chrome的这个方法虽然,你从浏览器要求警告“此网站试图下载多个文件。你要允许这样做?[禁止] [允许]”。因此,如果您在扩展程序的后台页面中执行此操作,后台页面会收到警告,但用户看不到它,因此用户无法单击“允许”。

解决方法是创建一个“点击”锚点的选项卡。事情是这样的:

function _anchorDownloader(url, filename) { 
    var timeout = 500; 
    return 'javascript:\'<!doctype html><html>'+ 
    '<head></head>' + 
    '<script>' + 
     'function initDownload() {'+ 
     'var el = document.getElementById("anchor");'+ 
     'el.click();' + 
     'setTimeout(function() { window.close(); }, ' + timeout + ');' + 
     '}'+ 
    '</script>' + 
    '<body onload="initDownload()">' + 
     '<a id="anchor" href="' + url + '" download="'+ filename + '"></a>'+ 
    '</body>' + 
    '</html>\''; 
}; 

function downloadResource(info, tab) { 
    // ... 
    chrome.tabs.create({ 'url' : _anchorDownloader(url, filename), 'active' : false }); 
    // ... 
} 

chrome.contextMenus.create({"title": "Save Image…", "contexts":["image"], "onclick": downloadResource }); 

对于这项工作,扩展必须具有"tabs"作为的manifest.json一个permission。您可以调整超时以关闭该选项卡,但是,如果您关闭它太快,则不会发生下载。

+0

我对此抱有很高的期望,但Chrome浏览器仍然屏蔽了多个发送事件。我不是试图在相同的链接上点击3次,而是3个不同的链接,甚至不一定在同一页面上。只有第一个在这里“点击” – coneybeare

+0

我想我明白你的意思。尝试在元素上使用MouseEvent/dispatchEvent,而不将其添加到/从文档中移除。因此,只需创建它,分配属性并分派事件,而无需追加/删除。我只是在Chrome 25.0.1364.172上试过,它对我很有用。 – zertosh

+0

有没有办法创建一个元素而不添加它? createElement()似乎可以兼得。 – coneybeare