使用 puppeteer 生成 PDF 而不保存
Posted
技术标签:
【中文标题】使用 puppeteer 生成 PDF 而不保存【英文标题】:Generate PDF with puppeteer without save it 【发布时间】:2019-04-09 18:22:47 【问题描述】:我有一个用 node.js
编写的 API,托管在 heroku
上,我的前端应用程序是用 Vue.js
编写的,它在 hostinger
上。我想知道是否可以使用 puppeteer 生成 PDF 文件并立即将其发送到前端客户端而不先将其保存到磁盘?如果是的话,你能给我举个例子吗?
目前我的功能是这样的:
exports.gerarPDFAvaliacao = async (dadosAvaliacao) =>
try
const compile = async (fileName, data) =>
const filePath = path.join(process.cwd(), 'src/templates/client/operation/', `$fileName.hbs`);
const html = await fs.readFile(filePath, 'utf-8');
return await hbs.compile(html)(data);
const browser = await puppeteer.launch();
const page = await browser.newPage();
let content = await compile('avaliations', dadosAvaliacao);
await page.goto(`data:text/html,$content`, waitUntil: 'networkidle0' );
await page.emulateMedia('screen');
await page.pdf(
path: 'src/dist/pdf/' + dadosAvaliacao.arquivo + '.pdf',
format: 'A4',
printBackground: true
)
await browser.close();
return dadosAvaliacao.arquivo + '.pdf';
catch (error)
console.log('Errors => ', error);
;
【问题讨论】:
【参考方案1】:根据official documentation,如果您不提供路径,文件将不会保存到磁盘。
page.pdf(选项): 可能具有以下属性的选项对象: path 保存 PDF 的文件路径。如果 path 是相对路径,则相对于当前工作目录进行解析。如果没有提供路径,PDF 将不会保存到磁盘。
这意味着它应该返回类似于缓冲区或生成文件的二进制表示的东西。您只需将其返回或通过管道将其返回到响应中,具体取决于您使用的框架。
这只是将 pdf 输出到控制台:
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.content());
const pdf = await page.pdf();
await browser.close();
console.log(pdf) // maybe do response(pdf).type('x-pdf')
编辑:这是一个使用 express 和 puppeteer 的完整示例,它直接在内存中返回 pdf 内容。它在 runkit 上运行,所以我认为同样的限制也适用(也许更多)。如果您导航到示例具有的公共端点,您可以看到浏览器如何检测到它是一个 pdf 文件并正确呈现它。
公开网址: https://puppeteer-express-pdf-export-w3o8ip7k207y.runkit.sh/ Runkit 笔记本:https://runkit.com/danielo515/puppeteer-express-pdf-export代码
const puppeteer = require ('puppeteer');
const express = require('express');
var app = express(exports);
const browser = await puppeteer.launch();
const main = async () =>
const page = await browser.newPage();
await page.goto('https://example.com');
const pdf = await page.pdf();
return pdf;
app.get('/', async function (req, res)
const pdf = await main();
res.contentType("application/pdf");
res.send(pdf);
);
app.listen(3000, function() console.log('Listening on 3000') );
【讨论】:
Danielo515,我已经编辑了我的问题并插入了我的函数。如您所见,我使用车把生成模板,然后将其传递给 puppeteer 以创建 pdf 文件。然后最后我把文件的路径返回到前面。 是的,你可以这样做。但正如我在示例中所展示的,如果您不提供路径,则该文件将在内存中生成,您可以将其保存到一个变量中,然后以正确的编码返回它。两种方法都可以,但您要求的方法不需要将文件保存到磁盘。 多亏了你,我快到了。现在,我可以将缓冲区传递到我的前端,但我不知道如何在前端应用程序(vuejs)中将此缓冲区呈现为 pdf 文件! =( 如果您根据从服务器返回的 mime 类型触发前端应用程序的获取,浏览器可能会自动下载文件。如果您使用的是 express,那么在执行res(content)
之前,它可能就像 res.header('Content-type', 'application/pdf');
一样简单。如果这不起作用,您始终可以通过动态创建链接在客户端下载为 blob。这是我用于非常大的 CSV 文件的示例:***.com/a/31438726/1734815
非常感谢您的关注,Danielo。我已经解决了将缓冲区更改为 base64 的问题。因此,我收到缓冲区并将其转换为 base64。在前面我创建了一个新的 Blob 并创建了 pdf。以上是关于使用 puppeteer 生成 PDF 而不保存的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 puppeteer 和 Node js 为 pdf 页面生成屏幕截图
使用特定配置打开 Puppeteer(下载 PDF 而不是 PDF 查看器)