You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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;

关键说明

  1. PDFNet初始化:必须在使用前调用PDFNet.initialize(),确保库功能正常启用。
  2. 加密配置:通过Encrypt.create()创建加密规则,可自定义打开密码和文档权限(比如允许打印则移除e_no_print参数)。
  3. 内存操作:全程基于buffer在内存中完成转换与加密,无需写入磁盘,适配Azure Function的无文件系统权限场景。
  4. 兼容性:@pdftron/pdfnet-node对PDF标准支持完善,避免了其他库常见的API兼容性报错。

内容的提问来源于stack exchange,提问作者ADLSistemas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 16:27:20