it-swarm.com.de

Wie kann ich eine Datei mit Puppenspieler mit Headless herunterladen: true?

Ich habe den folgenden Code ausgeführt, um eine csv-Datei von der Website http://niftyindices.com/resources/holiday-calendar herunterzuladen:

const puppeteer = require('puppeteer');

(async () => {
const browser = await puppeteer.launch({headless: true});
const page = await browser.newPage();

await page.goto('http://niftyindices.com/resources/holiday-calendar');
await page._client.send('Page.setDownloadBehavior', {behavior: 'allow', 
downloadPath: '/tmp'})
await page.click('#exportholidaycalender');
await page.waitFor(5000);
await browser.close();
})();

mit headless: false funktioniert es, es lädt die Datei in /Users/user/Downloads herunter. mit headless: true funktioniert es NICHT.

Ich verwende dies auf einem macOS Sierra (MacBook Pro) mit der Puppenspielerversion 1.1.1, die die Chromium-Version 66.0.3347.0 in das .local-chromium/-Verzeichnis zieht und npm init und npm i --save puppeteer zum Einrichten verwendet.

Irgendeine Idee, was ist falsch?

Vielen Dank im Voraus für Ihre Zeit und Hilfe.

Auf dieser Seite wird eine CSV-Datei heruntergeladen, indem eine durch Kommas getrennte Zeichenfolge erstellt und der Browser zum Herunterladen gezwungen wird, indem der Datentyp so festgelegt wird

let uri = "data:text/csv;charset=utf-8," + encodeURIComponent(content);
window.open(uri, "Some CSV");

Dies auf Chrome öffnet eine neue Registerkarte.

Sie können auf dieses Ereignis zugreifen und den Inhalt physisch in eine Datei herunterladen. Nicht sicher, ob dies der beste Weg ist, aber gut funktioniert.

const browser = await puppeteer.launch({
  headless: true
});
browser.on('targetcreated', async (target) => {
    let s = target.url();
    //the test opens an about:blank to start - ignore this
    if (s == 'about:blank') {
        return;
    }
    //unencode the characters after removing the content type
    s = s.replace("data:text/csv;charset=utf-8,", "");
    //clean up string by unencoding the %xx
    ...
    fs.writeFile("/tmp/download.csv", s, function(err) {
        if(err) {
            console.log(err);
            return;
        }
        console.log("The file was saved!");
    }); 
});

const page = await browser.newPage();
.. open link ...
.. click on download link ..
5
Sumit Mishra

Das Problem ist, dass der Browser geschlossen wird, bevor der Download abgeschlossen ist.

Sie können die Dateigröße und den Namen der Datei aus der Antwort abrufen und dann mithilfe eines Überwachungsskripts die Dateigröße anhand der heruntergeladenen Datei überprüfen, um den Browser zu schließen.

Dies ist ein Beispiel:

const filename = <set this with some regex in response>;
const dir = <watch folder or file>;

// Download and wait for download
    await Promise.all([
        page.click('#DownloadFile'),
       // Event on all responses
        page.on('response', response => {
            // If response has a file on it
            if (response._headers['content-disposition'] === `attachment;filename=${filename}`) {
               // Get the size
                console.log('Size del header: ', response._headers['content-length']);
                // Watch event on download folder or file
                 fs.watchFile(dir, function (curr, prev) {
                   // If current size eq to size from response then close
                    if (parseInt(curr.size) === parseInt(response._headers['content-length'])) {
                        browser.close();
                        this.close();
                    }
                });
            }
        })
    ]);

Sogar, dass die Art der Suche als Antwort verbessert werden kann, obwohl ich hoffe, dass Sie dies nützlich finden werden.

Gestern habe ich stundenlang durch diesen Thread und Stack Overflow gebastelt, um herauszufinden, wie man Puppenspieler dazu bringt, eine csv-Datei herunterzuladen, indem in einer authentifizierten Sitzung im Headless-Modus auf einen Download-Link geklickt wird. Die akzeptierte Antwort hier hat in meinem Fall nicht funktioniert, da der Download keine targetcreated auslöst und die nächste Antwort aus irgendeinem Grund die authentifizierte Sitzung nicht beibehalten hat. Dieser Artikel hat den Tag gerettet. Kurz gesagt, fetch. Hoffentlich hilft das jemand anderen.

const res = await this.page.evaluate(() =>
{
    return fetch('https://example.com/path/to/file.csv', {
        method: 'GET',
        credentials: 'include'
    }).then(r => r.text());
});
1
MyCompassSpins

Ich musste eine Datei hinter einem Login herunterladen, das vom Puppenspieler bearbeitet wurde. targetcreated wurde nicht ausgelöst. Am Ende habe ich mit request heruntergeladen, nachdem ich die Cookies von der Puppeteer-Instanz übernommen habe.

In diesem Fall streame ich die Datei durch, aber Sie können sie genauso einfach speichern.

    res.writeHead(200, {
        "Content-Type": 'application/octet-stream',
        "Content-Disposition": `attachment; filename=secretfile.jpg`
    });
    let cookies = await page.cookies();
    let jar = request.jar();
    for (let cookie of cookies) {
        jar.setCookie(`${cookie.name}=${cookie.value}`, "http://secretsite.com");
    }
    try {
        var response = await request({ url: "http://secretsite.com/secretfile.jpg", jar }).pipe(res);
    } catch(err) {
        console.trace(err);
        return res.send({ status: "error", message: err });
    }
0

Ich habe eine andere Lösung für dieses Problem, da keine der Antworten hier für mich funktioniert hat.

Ich musste mich auf einer Website anmelden und einige CSV-Berichte herunterladen. Headed war in Ordnung, Headless versagte, egal was ich versuchte. Bei den Netzwerkfehlern wird der Download abgebrochen, aber ich konnte (schnell) nicht feststellen, warum.

Also habe ich die Anfragen abgefangen und Node-Fetch verwendet, um die Anfrage außerhalb des Puppenspielers zu stellen. Dies erforderte das Kopieren der Abrufoptionen, des Hauptteils, der Header und das Hinzufügen des Zugriffscookies.

Viel Glück.

0