如何在Next.js API路由使用pdfkit生成PDF?附客户端方案
在Next.js API路由中使用pdfkit生成PDF的解决方案
问题背景
我正在开发一个需要使用pdfkit库生成PDF的项目,该功能已在Express.js服务器中正常运行,但在Next.js API路由中实现时遇到问题。
可用的Express.js代码(src/index.ts):
import express from 'express'; import PDFDocument from 'pdfkit'; const app = express(); app.get('/', (req, res) => { const doc = new PDFDocument(); doc.text("hello hello hello HI"); doc.end(); doc.pipe(res); }); const port = parseInt(process.env.PORT) || 3000; app.listen(port, () => { console.log(`listening on port ${port}`); });
访问根URL时,该代码可正常生成预期的PDF文件。
当前无法工作的Next.js API路由代码(api/route.ts):
import PDFDocument from 'pdfkit'; import { NextResponse } from 'next/server'; export async function GET(request: Request) { const doc = new PDFDocument(); doc.text("hello hello hello HI"); doc.end(); doc.pipe(NextResponse); }
在Next.js应用中访问对应API路由时,无法生成PDF且出现错误。
已尝试的操作:
- 确认
pdfkit已正确安装并导入。 - 确认API路由已正确配置且可访问。
解决方案
1. Next.js API路由的正确实现
Next.js的API路由(App Router)需要返回完整的Response对象,不能直接将pdfkit的流pipe到NextResponse。需先将PDF流收集到缓冲区,再构建带正确头信息的响应:
import PDFDocument from 'pdfkit'; import { NextResponse } from 'next/server'; export async function GET(request: Request) { return new Promise<NextResponse>((resolve) => { const doc = new PDFDocument(); const chunks: Uint8Array[] = []; // 收集流数据到缓冲区 doc.on('data', (chunk) => chunks.push(chunk)); doc.on('end', () => { const pdfBuffer = Buffer.concat(chunks); // 构建响应并设置必要的HTTP头 const response = new NextResponse(pdfBuffer, { headers: { 'Content-Type': 'application/pdf', 'Content-Disposition': 'inline; filename="output.pdf"', // 替换为`attachment`可触发下载 }, }); resolve(response); }); // 添加PDF内容 doc.text("hello hello hello HI"); doc.end(); }); }
2. 和Express.js实现的差异
- 流处理逻辑不同:Express的
res是原生可写流,pdfkit可直接pipe到res,由Express自动完成响应发送;Next.js API路由要求手动收集流数据,构建完整的Response实例返回。 - 响应头配置:Next.js需要显式设置
Content-Type、Content-Disposition等头信息,而Express会自动处理部分默认头。
3. 客户端浏览器生成PDF的方案
若无需服务器端生成,可直接在前端实现:
- pdfkit-browser:
pdfkit的浏览器兼容版本,可在前端生成PDF并通过Blob下载。 - jsPDF:轻量前端PDF库,API简洁,适合简单PDF需求。
- html2pdf.js:直接将页面HTML元素转换为PDF,适合基于现有页面内容生成PDF的场景。
客户端示例(pdfkit-browser):
// 安装依赖:npm install pdfkit-browser import PDFDocument from 'pdfkit-browser'; function generateClientPDF() { const doc = new PDFDocument(); const chunks = []; doc.on('data', (chunk) => chunks.push(chunk)); doc.on('end', () => { const blob = new Blob(chunks, { type: 'application/pdf' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = 'client-generated.pdf'; link.click(); URL.revokeObjectURL(url); }); doc.text("Hello from client-side PDF!"); doc.end(); }
内容的提问来源于stack exchange,提问作者Tafsir Chowdhury
相关产品推荐
相关产品推荐

