请求基于Node.js的PDFKit预定义模板生成PDF的参考示例
当然有!我刚好做过类似的实现,给你一套完整的示例流程,从前端表单到后端用PDFKit生成带模板的PDF,完全贴合你的需求:
整体流程概述
整个实现逻辑很清晰:
- 前端搭建表单收集用户输入数据
- 提交请求到Node.js后端
- 后端用PDFKit调用预定义的模板逻辑(固定样式+动态数据插入)生成PDF
- 将生成的PDF流式返回给前端,触发下载
1. 前端表单实现(HTML+JS)
先写一个简单的用户信息收集表单,包含基础输入项和提交逻辑,用fetch发送数据到后端:
<!DOCTYPE html> <html> <head> <title>PDF生成工具</title> <style> form { max-width: 500px; margin: 2rem auto; display: flex; flex-direction: column; gap: 1rem; } input, textarea { padding: 0.5rem; font-size: 1rem; } button { padding: 0.7rem; background: #2563eb; color: white; border: none; border-radius: 4px; cursor: pointer; } </style> </head> <body> <form id="pdfGeneratorForm"> <div> <label>姓名:</label> <input type="text" name="fullName" required placeholder="请输入姓名"> </div> <div> <label>联系邮箱:</label> <input type="email" name="email" required placeholder="example@xxx.com"> </div> <div> <label>个人简介:</label> <textarea name="bio" rows="4" required placeholder="简单介绍一下自己"></textarea> </div> <button type="submit">生成个人PDF档案</button> </form> <script> const form = document.getElementById('pdfGeneratorForm'); form.addEventListener('submit', async (e) => { e.preventDefault(); const submitBtn = form.querySelector('button'); submitBtn.disabled = true; submitBtn.textContent = '生成中...'; try { const formData = new FormData(form); const userData = Object.fromEntries(formData); // 发送请求到后端 const response = await fetch('/generate-profile-pdf', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(userData) }); if (!response.ok) throw new Error('PDF生成失败,请重试'); // 处理返回的PDF文件并触发下载 const blob = await response.blob(); const downloadUrl = window.URL.createObjectURL(blob); const aTag = document.createElement('a'); aTag.href = downloadUrl; aTag.download = `${userData.fullName}_个人档案.pdf`; aTag.click(); window.URL.revokeObjectURL(downloadUrl); } catch (err) { alert(err.message); } finally { submitBtn.disabled = false; submitBtn.textContent = '生成个人PDF档案'; } }); </script> </body> </html>
2. Node.js后端实现(Express + PDFKit)
首先安装依赖:
npm install express pdfkit cors
然后编写后端代码,核心是封装一个PDF模板函数,把固定内容(比如标题、页眉页脚)和动态用户数据结合起来:
const express = require('express'); const PDFDocument = require('pdfkit'); const cors = require('cors'); const app = express(); const PORT = 3000; // 中间件配置 app.use(cors()); app.use(express.json()); app.use(express.static('public')); // 把前端HTML放在public目录下托管 // 封装PDF模板:接收用户数据,返回PDFKit文档实例 function generateProfilePDF(userData) { const doc = new PDFDocument({ margin: 60 }); // 页眉:标题+分隔线 doc.fontSize(22).font('Helvetica-Bold').text('个人档案', { align: 'center' }); doc.moveDown(0.5); doc.lineWidth(1).moveTo(60, 80).lineTo(550, 80).stroke(); doc.moveDown(1.2); // 动态数据区域:固定标签+用户输入内容 doc.fontSize(14).font('Helvetica-Bold').text('基本信息', 60); doc.moveDown(0.8); doc.font('Helvetica').fontSize(12); doc.text(`姓名: ${userData.fullName}`, 60); doc.moveDown(0.5); doc.text(`邮箱: ${userData.email}`, 60); doc.moveDown(1); doc.fontSize(14).font('Helvetica-Bold').text('个人简介', 60); doc.moveDown(0.8); doc.font('Helvetica').fontSize(12).text(userData.bio, 60, undefined, { width: 480, align: 'justify' }); // 页脚:生成时间 doc.moveDown(3); doc.fontSize(10).text(`生成时间: ${new Date().toLocaleString('zh-CN')}`, { align: 'center' }); return doc; } // 处理PDF生成请求的接口 app.post('/generate-profile-pdf', (req, res) => { const userData = req.body; const pdfDoc = generateProfilePDF(userData); // 设置响应头,告诉浏览器这是PDF文件 res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${userData.fullName}_个人档案.pdf"`); // 流式传输PDF到前端 pdfDoc.pipe(res); pdfDoc.end(); }); // 启动服务器 app.listen(PORT, () => { console.log(`服务器运行在 http://localhost:${PORT}`); });
3. 进阶优化建议
- 复杂模板扩展:如果需要添加Logo、表格等元素,可以用
doc.image('path/to/logo.png', x, y, { width: 100 })插入图片;如果需要表格,可以安装pdfkit-table包来快速生成结构化表格。 - 模板模块化:把不同的PDF模板抽成单独的文件(比如
templates/profileTemplate.js、templates/invoiceTemplate.js),便于维护多个模板。 - 数据校验:后端可以添加Joi等校验库,对前端传入的数据进行合法性校验,避免生成无效PDF。
- 性能优化:PDFKit本身是流式生成PDF,适合处理大量请求;如果是高并发场景,可以考虑用Redis做请求限流。
内容的提问来源于stack exchange,提问作者DavidB
相关产品推荐
相关产品推荐

