此用户使用Puppeteer代码的路由:
Router.get('/generate_invoice', (req, res) => {
const userData = req.session.user;
res.render("./patientpanel/invoice", { user: userData });
(async () => {
// launch a new chrome instance
const browser = await puppeteer.launch({
headless: true
});
const page = await browser.newPage();
const filePathName = path.resolve(__dirname, '../views/patientpanel/invoice.ejs');
const html = fs.readFileSync(filePathName, 'utf8')
await page.goto("http://localhost:5000/generate_invoice" + html);
await page.setContent(html, {
waitUntil: 'domcontentloaded'
});
const pdfBuffer = await page.pdf({
format: 'A4'
});
// or a .pdf file
await page.pdf({ path: "./user.pdf", format: pdfBuffer });
await browser.close()
})();
});
PDF文件生成成功,但它显示了EJS模板,因为它没有任何适当的格式和数据,我通过上面的路由器呈现。
EJS模板代码:
<tr class="information">
<td colspan="2">
<table>
<tr>
<td>
Name: <%- user.firstname %>
<%- user.lastname %><br />
Email: <%- user.email %><br />
Mobile No. : <%- user.mob %>
</td>
</tr>
</table>
</td>
</tr>
发布于 2022-11-04 20:33:35
基本的误解似乎是熟悉与Express (例如res.render()
)结合在一起的EJS,而不是独立的。EJS提供了分别处理文件和普通字符串的renderFile
和render
方法。您想要使用这些来准备HTML,然后将其放入Puppeteer,PDF'd,然后作为响应发送。
下面是处理请求的基本工作流:
.-------------------.
| EJS template file |
`-------------------`
|
[ejs.renderFile]
|
v
.-------------.
| HTML string |
`-------------`
|
[page.setContent]
|
v
.-------------.
| browser tab |
`-------------`
|
[page.pdf]
|
v
.------------.
| PDF buffer |
`------------`
|
[res.send]
|
v
.----------.
| response |
`----------`
下面是一个您可以使用的完整示例(我简化了路径,以便在没有文件夹结构的情况下更容易地复制;模板位于与服务器代码相同的目录中):
const ejs = require("ejs"); // 3.1.8
const express = require("express"); // ^4.18.1
const puppeteer = require("puppeteer"); // ^19.1.0
express()
.get("/generate-invoice", (req, res) => {
const userData = { // for example
firstname: "linus",
lastname: "torvalds",
email: "foo@bar.com",
mob: "900-900-9000"
};
let browser;
(async () => {
browser = await puppeteer.launch();
const [page] = await browser.pages();
const html = await ejs.renderFile("invoice.ejs", {user: userData});
await page.setContent(html);
const pdf = await page.pdf({format: "A4"});
res.contentType("application/pdf");
// optionally:
res.setHeader(
"Content-Disposition",
"attachment; filename=invoice.pdf"
);
res.send(pdf);
})()
.catch(err => {
console.error(err);
res.sendStatus(500);
})
.finally(() => browser?.close());
})
.listen(3000);
导航到http://localhost:3000/generate-invoice
以进行测试。
您可以使用ejs.render()
和fs.readFile
在应用程序开始时立即将文件提取进来,在每个ejs.renderFile
请求上保存一个额外的文件。
顺便说一句,在每个请求上启动浏览器有点麻烦,所以您可以考虑使用一个浏览器和多个页面。有关潜在的方法,请参见this answer。
https://stackoverflow.com/questions/74255357
复制相似问题