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