Я изо всех сил пытаюсь заставить Puppeteer загрузить файл в браузере. В настоящее время он сохраняет файл локально в Cloud9, но я хочу нажать кнопку загрузки PDF и загрузить его в Chrome.
Я пытался сохранить page.pdf в переменную, но это не сработало. Я также пытался открыть локально сохраненный файл, но я тоже не могу заставить его работать.
var express = require("express");
var puppeteer = require("puppeteer");
module.exports = function pdf(url, req) {(async () => {
var browser = await puppeteer.launch();
var page = await browser.newPage();
await page.goto('https://node-and-mysql-mbegg.c9users.io/clients/'+req.params.id+'/reports/monthlyreport/'+req.params.marketplace+'/'+req.params.month, {waitUntil: 'networkidle2'});
await page.pdf({path: 'public/temp/Performance Report -'+req.params.month+'.pdf', format: 'A4', landscape: true, printBackground: true});
await browser.close();
})();
}
///Print PDF route
router.get("/clients/:id/reports/monthlyreport/:marketplace/:month/pdf", function(req, res) {
var url = "/clients/"+req.params.id+"/reports/monthlyreport/"+req.params.marketplace+"/"+req.params.month
pdf(url, req);
res.contentType("application/pdf");
res.send(pdf);;
});
Я знаю, что res.send(pdf) требует, чтобы page.pdf() сохранялся в переменной и возвращался. Я просто не убрал это из маршрута.
Что происходит, когда я сохраняю page.pdf() в переменную, так это то, что я просто получаю пустой файл, а не PDF, и он выглядит просто как пустой буфер или что-то в этом роде. Я не знаю, что я делаю неправильно, чтобы не загрузить файл в браузере Chrome.
/// Async/await
router.get("/clients/:id/reports/monthlyreport/:marketplace/:month/pdf", async function(req, res) {
var url = "/clients/"+req.params.id+"/reports/monthlyreport/"+req.params.marketplace+"/"+req.params.month
let pdfData = await pdf(url, req);
res.contentType("application/pdf");
res.send(pdfData);
});
/// promise
router.get("/clients/:id/reports/monthlyreport/:marketplace/:month/pdf", async function(req, res) {
var url = "/clients/"+req.params.id+"/reports/monthlyreport/"+req.params.marketplace+"/"+req.params.month
pdf(url, req).then((pdfData )=>{
res.contentType("application/pdf");
res.send(pdfData);
});
});
Вы не ждали завершения процесса. Вы также отправили функцию, а не ее результат.
Не похоже, что я могу вызывать await вне асинхронности. Когда я включаю его в асинхронный режим, приложение ничего не выводит и время ожидания истекает.
Я исправил свое предложение async/await и добавил предложение на основе обещаний. Нормально, должны работать. Если нет, попробуйте отправить что-то еще, кроме pdfData, просто чтобы посмотреть, как он отреагирует...
В то время как в функции pdf
вы, кажется, ожидаете каждой из операций puppeteer
, на самом деле вы не ждете вызова функции pdf
в своем экспресс-маршруте. Кроме того, функция pdf
сейчас ничего не возвращает! Вам нужно будет внести следующие изменения в вашу программу:
pdf
должна возвращать имя файла, в котором был сохранен сгенерированный PDF-файл. Пока вы это делаете, вы можете избавиться от IIFE, это не обязательно, просто объявите внешнюю функцию как async
.pdf(...)
. Это можно сделать с помощью Promise или await. Если ожидание предпочтительнее, внешняя функция должна быть помечена как асинхронная.sendFile
, предоставляемая экспресс-объектами response
, должна использоваться для отправки сгенерированного PDF-файла клиенту. Обратите внимание, что res.sendFile
ожидает абсолютный путь к файлу.Ниже приведена модифицированная версия вашей программы, в которой они реализованы.
const express = require("express");
const puppeteer = require("puppeteer");
const path = require('path');
module.exports = async function pdf(url, req) {
const filename = `public/temp/Performance Report -${req.params.month}.pdf`;
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://node-and-mysql-mbegg.c9users.io/clients/'+req.params.id+'/reports/monthlyreport/'+req.params.marketplace+'/'+req.params.month, {waitUntil: 'networkidle2'});
await page.pdf({path: filename, format: 'A4', landscape: true, printBackground: true});
await browser.close();
return filename;
}
///Print PDF route
router.get("/clients/:id/reports/monthlyreport/:marketplace/:month/pdf", async function(req, res) {
var url = "/clients/"+req.params.id+"/reports/monthlyreport/"+req.params.marketplace+"/"+req.params.month
const filename = await pdf(url, req);
res.contentType("application/pdf");
res.sendFile(path.join(__dirname, filename)); // if 'public/temp/...' path is not relative to cur dir, make relevant change here.
});
Да, это сработало именно так, как мне было нужно. Просто нужно было изменить каталог файлов
Но подождите, так вы запускаете puppeteer на клиенте для создания PDF-файлов? Это означает, что ваши клиенты также будут загружать движок хрома, поскольку это то, что кукловод использует за кулисами. Кстати, насколько велико ваше развертывание?