如何在Node.js中为Puppeteer生成的PDF添加密码加密
问题描述
使用Puppeteer将HTML生成PDF并转为Base64返回,但无法为PDF添加打开密码保护。尝试过pdf-lib、pdfKit等库均失败,出现如encrypt is not a function之类的报错。当前实现代码如下:
//const pdf = require('html-pdf'); // var { Base64Encode } = require('base64-stream'); // const { PDFDocument, StandardFonts } = require('pdf-lib'); // const { JSDOM } = require('jsdom'); // const generatorPdf = require('jspdf'); //const base64 = require('base-64'); // require('jspdf-autotable'); const { PDFNet } = require('@pdftron/pdfnet-node'); const handlebars = require('handlebars'); const puppeteer = require('puppeteer'); const Buffer = require('buffer').Buffer; const moment = require('moment'); handlebars.registerHelper('formatDate', function (dateString) { return new handlebars.SafeString( moment(dateString).format("DD/MM/YYYY").toUpperCase() ); }); async function middleware(context, res) { let template = context.body.template || context.body.Template; const data = context.body.data || context.body.Data; let htmlContent = handlebars.compile(template, data)(data); const password = context.body.password || context.body.Password; return (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.setContent(htmlContent); const pdf = await page.pdf({ format: 'A4', printBackground: true }); await browser.close(); let result = { html: Buffer.from(pdf).toString('base64') } res.json(result); })(); } module.exports = middleware;
解决方案
你已经引入了@pdftron/pdfnet-node,这个库支持在内存中对PDF进行加密操作,完全适配Azure Function环境。修改后的完整代码如下:
const { PDFNet } = require('@pdftron/pdfnet-node'); const handlebars = require('handlebars'); const puppeteer = require('puppeteer'); const Buffer = require('buffer').Buffer; const moment = require('moment'); handlebars.registerHelper('formatDate', function (dateString) { return new handlebars.SafeString( moment(dateString).format("DD/MM/YYYY").toUpperCase() ); }); // 初始化PDFNet,必须在使用前执行 async function initPDFNet() { try { await PDFNet.initialize(); } catch (err) { console.error('PDFNet初始化失败:', err); throw err; } } async function encryptPDF(rawPdfBuffer, password) { const doc = await PDFNet.PDFDocument.createFromBuffer(rawPdfBuffer); // 设置加密参数:打开密码、权限密码(此处与打开密码一致,也可设置不同值) const encrypt = await PDFNet.Encrypt.create(); await encrypt.setPassword(password); // 设置文档权限:禁止打印、修改等,可根据需求调整 await encrypt.setPermissions(PDFNet.Encrypt.Permissions.e_no_print | PDFNet.Encrypt.Permissions.e_no_modify); // 应用加密并保存到内存buffer const encryptedBuffer = await doc.saveMemoryBuffer(encrypt); return encryptedBuffer; } async function middleware(context, res) { let template = context.body.template || context.body.Template; const data = context.body.data || context.body.Data; const password = context.body.password || context.body.Password; try { // 初始化PDFNet await initPDFNet(); // 用Puppeteer生成原始PDF const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.setContent(handlebars.compile(template)(data)); const rawPdf = await page.pdf({ format: 'A4', printBackground: true }); await browser.close(); // 加密PDF(如果传入了密码) let processedPdf = rawPdf; if (password) { processedPdf = await encryptPDF(rawPdf, password); } // 转Base64返回 const result = { html: Buffer.from(processedPdf).toString('base64') }; res.json(result); } catch (err) { console.error('处理失败:', err); res.status(500).json({ error: 'PDF生成或加密失败' }); } } module.exports = middleware;
关键说明
- PDFNet初始化:必须在使用前调用
PDFNet.initialize(),确保库功能正常启用。 - 加密配置:通过
Encrypt.create()创建加密规则,可自定义打开密码和文档权限(比如允许打印则移除e_no_print参数)。 - 内存操作:全程基于buffer在内存中完成转换与加密,无需写入磁盘,适配Azure Function的无文件系统权限场景。
- 兼容性:
@pdftron/pdfnet-node对PDF标准支持完善,避免了其他库常见的API兼容性报错。
内容的提问来源于stack exchange,提问作者ADLSistemas
相关产品推荐
相关产品推荐

