使用 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 而不保存的主要内容,如果未能解决你的问题,请参考以下文章

生成pdf而不将其保存到磁盘然后将其显示给浏览器

如何使用 puppeteer 和 Node js 为 pdf 页面生成屏幕截图

使用特定配置打开 Puppeteer(下载 PDF 而不是 PDF 查看器)

玩转Puppeteer

使用 SelectPdf .NET 在电子邮件中附加 pdf 而不保存 PDF

如何使用CakePdf创建和下载PDF,而不是在浏览器中显示它