web-dev-qa-db-fra.com

Comment télécharger un fichier avec le marionnettiste en utilisant headless: true?

J'ai utilisé le code suivant pour télécharger un fichier csv à partir du site Web http://niftyindices.com/resources/holiday-calendar:

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

avec headless: false cela fonctionne, il télécharge le fichier dans /Users/user/Downloads. avec headless: true cela ne fonctionne pas.

J'utilise cette application sur un Mac OS (MacBook Pro) utilisant la version 1.1.1 de marionnettiste, qui récupère la version 66.0.3347.0 de Chromium dans le répertoire .local-chromium/ et utilise npm init et npm i --save puppeteer pour la configurer.

Une idée de ce qui ne va pas?

Merci d'avance pour votre temps et votre aide,

13

Cette page télécharge un csv en créant une chaîne délimitée par des virgules et en forçant le navigateur à le télécharger en définissant le type de données de la manière suivante

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

Ceci sur le chrome ouvre un nouvel onglet.

Vous pouvez accéder à cet événement et télécharger physiquement le contenu dans un fichier. Je ne sais pas si c'est la meilleure façon mais ça fonctionne bien.

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

Le problème est que le navigateur se ferme avant la fin du téléchargement.

Vous pouvez obtenir la taille du fichier et le nom du fichier à partir de la réponse, puis utiliser un script de surveillance pour vérifier la taille du fichier téléchargé, afin de fermer le navigateur.

Ceci est un exemple:

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

Même si la façon de chercher en réponse peut être améliorée, j'espère que vous le trouverez utile.

3

J'ai passé des heures à parcourir ce fil et Stack Overflow hier, à essayer de trouver un moyen de faire télécharger un fichier csv à Puppeteer en cliquant sur un lien de téléchargement en mode sans tête dans une session authentifiée. La réponse acceptée ici ne fonctionne pas dans mon cas car le téléchargement ne déclenche pas targetcreated, et la réponse suivante, pour une raison quelconque, ne conserve pas la session authentifiée. Cet article a sauvé la journée. En bref, fetch. Espérons que cela aide quelqu'un d'autre.

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

Je devais télécharger un fichier derrière une connexion, qui était gérée par Puppeteer. targetcreated n'était pas déclenché. Finalement, j'ai téléchargé avec request, après avoir copié les cookies de l'instance de Puppeteer.

Dans ce cas, je diffuse le fichier en continu, mais vous pouvez tout aussi bien le sauvegarder.

    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