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

请求基于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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:45:42