6

Próbuję pobrać wiele plików w rozszerzeniu Chrome. Poniższy kod tworzy fikcyjne łącze do pliku, a następnie wyzwala zdarzenie .click(), które pobiera plik. Problem polega na tym, że tylko pierwsze zdarzenie .click() wyzwala pobieranie. Kolejne zdarzenia .click() są ignorowane.Metoda click() JavaScript działa tylko raz w rozszerzeniu Chrome

Tutaj 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 
} 

tu 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"}); 
}); 

próbowałem:

Zaskoczony, dlaczego tak trudno jest po prostu zapisać wiele plików. Doceniam każdą pomoc.

+1

Poczekaj kilka miesięcy, a ["chrome.downloads"] (https://developer.chrome.com/dev/extensions/downloads.html) API jest szeroko dostępny. O błędzie CSP: 'a' jest łączem, którego właściwość' toString' zwraca cel łącza. Tak więc, jeśli użyjesz 'setTimeout (a, 300);', spróbuje ocenić cel łącza. Ocena łańcuchów jako kodu jest domyślnie zabroniona, więc pojawia się błąd. Jeśli użyjesz 'setTimeout (function() {a.click();}, 300);', plik nadal nie jest pobierany. –

+0

Czy znalazłeś tymczasowe rozwiązanie tego problemu? – coneybeare

+0

Myślę, że nie jest to możliwe z powodu problemu z bezpieczeństwem. Gdyby było to możliwe, wirtualnie mogłem otworzyć nieskończone wyskakujące okienko/pobieranie jednym kliknięciem. –

Odpowiedz

0

Zamiast .live() methode który nie jest już zalecany spróbować .on()

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

oto documentation

+0

Dzięki za podpowiedź, ale niestety to nie pomogło. – toby88

4

Sztuką jest, aby nie używać metody element.click ale raczej tworzenie wielu MouseEvent. Aby to zadziałało, musisz utworzyć jedną MouseEvent za każdym razem, gdy potrzebujesz kliknięcia.

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. 

Podczas stosowania tej metody w Chrome choć można dostać ostrzeżenie od przeglądarki prośbą „Witryna próbuje pobrać wiele plików. Czy chcesz na to zezwolić? [Deny] [Zezwalaj]”. Tak więc, jeśli robisz to na stronie w tle rozszerzenia, strona w tle otrzymuje ostrzeżenie, użytkownik nie może go zobaczyć, więc użytkownik nie ma możliwości kliknięcia "Zezwalaj".

Obejście problemu (brutto/nasty) polega na utworzeniu karty, która "klika" kotwicę. Coś takiego:

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 }); 

Aby to działało, rozszerzenie musi mieć "tabs" jako permission w manifest.json. Możesz zmienić czas oczekiwania, aby zamknąć kartę, jednak jeśli zamkniesz ją zbyt szybko, pobieranie nie będzie możliwe.

+0

Miałem na to duże nadzieje, ale wygląda na to, że Chrome nadal blokuje więcej niż jedno zdarzenie wysyłkowe. Nie próbuję "klikać" na tym samym łączu 3 razy, ale raczej 3 różne, nawet na tej samej stronie. Tylko pierwszy został "kliknięty" tutaj. – coneybeare

+0

Myślę, że rozumiem, co masz na myśli. Wypróbuj MouseEvent/dispatchEvent na elemencie bez dołączania/usuwania go do/z dokumentu. Stwórz go, przypisz właściwości i wyślij wydarzenie, nigdy nie dołączając/usuwając. Właśnie wypróbowałem to w Chrome 25.0.1364.172 i zadziałało to dla mnie. – zertosh

+0

Czy istnieje sposób na stworzenie elementu, a nie dodanie go? Metoda createElement() wydaje się robić obie. – coneybeare

Powiązane problemy