Node.js Web应用如何实现点击按钮将页面转换为PDF并下载查看
最优实现方案:使用Puppeteer渲染EJS页面生成PDF
Puppeteer是Google官方维护的无头浏览器工具,可以完美渲染EJS生成的HTML页面(兼容CSS、JS样式逻辑),直接导出标准PDF文件,是当前场景下兼容性最好、效果最可控的方案。
实现步骤
1. 安装依赖
npm install puppeteer
2. 改造generatePDF处理函数
核心逻辑调整为:先获取EJS渲染完成的HTML字符串 → 喂给Puppeteer生成PDF → 把PDF流返回给前端,支持在线预览或直接下载。
const puppeteer = require('puppeteer'); // 建议全局复用浏览器实例,避免每次请求重复启动浏览器提升性能 let browserInstance = null; const initBrowser = async () => { if (!browserInstance) { // 服务器部署时需要添加--no-sandbox等启动参数 browserInstance = await puppeteer.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] }); } return browserInstance; }; const generatePDF = async (request, response) => { try { const browser = await initBrowser(); const page = await browser.newPage(); // 第一步:获取EJS渲染后的完整HTML字符串,替换原来直接response.render的逻辑 const renderData = { /* 你原来传给EJS模板的变量 */ }; const htmlContent = await new Promise((resolve, reject) => { response.render('pages/pagetoconverttoPDF', renderData, (err, html) => { if (err) return reject(err); resolve(html); }); }); // 第二步:加载HTML并生成PDF await page.setContent(htmlContent, { waitUntil: 'networkidle0' }); const pdfBuffer = await page.pdf({ format: 'A4', // 纸张规格 printBackground: true, // 是否打印背景样式 margin: { // 边距配置 top: '20px', right: '20px', bottom: '20px', left: '20px' } }); await page.close(); // 第三步:返回PDF给前端 // 配置响应头:inline为在线预览,attachment为直接下载 response.setHeader('Content-Type', 'application/pdf'); response.setHeader('Content-Disposition', 'inline; filename="导出文件.pdf"'); response.send(pdfBuffer); } catch (err) { console.error('生成PDF失败:', err); response.status(500).send('PDF生成失败'); } } module.exports = { generatePDF, }
注意事项
- 如果服务器环境无法安装Puppeteer完整依赖,可替换为
puppeteer-core配合系统已安装的Chrome使用 - 如果页面中有大量异步加载的内容,可调整
setContent的waitUntil参数,或添加page.waitForSelector等待指定元素加载完成后再生成PDF - 生产环境需要做好浏览器实例的异常处理,避免实例崩溃后无法正常生成PDF
内容的提问来源于stack exchange,提问作者NicLovin
相关产品推荐
相关产品推荐

