Next.js API 如何将PDF Buffer作为附件下载到浏览器
问题原因
你当前的代码有4个核心问题,导致无法正常触发PDF下载:
- 异步逻辑等待无效:
createReport是回调风格的函数,本身不返回Promise,你加的await不会等待回调执行完成,外层路由处理函数执行结束时Next.js会自动返回空响应,回调里的响应设置、发送逻辑根本不会生效。 - 缺少必要响应头:没有设置
Content-Length头,浏览器无法正确识别文件大小,容易出现下载中断、文件损坏的问题。 - 响应发送方式有误:
res.send()会自动对传入内容做字符串编码检测和转换,处理二进制PDF Buffer时容易破坏文件结构,导致下载后的PDF打不开。 - 未指定运行时:如果你的Next.js项目默认开启了Edge Runtime,Node.js原生Buffer类型在Edge环境下存在兼容问题,会导致返回内容乱码。
另外确认你是否在文件末尾导出了handler,未导出的话Next.js无法识别该路由处理函数。
修复代码
import type { NextApiRequest, NextApiResponse } from 'next' // 强制该路由使用Node.js运行时,规避Edge Runtime的Buffer兼容问题 export const config = { runtime: 'nodejs', } const handler = async (req: NextApiRequest, res: NextApiResponse) => { // 将回调风格的createReport包装为Promise,确保异步逻辑执行完成后再发送响应 const pdfBuffer = await new Promise<Buffer>((resolve, reject) => { try { createReport(null, 'Employee', (buffer: Buffer) => { resolve(buffer) }) } catch (err) { reject(err) } }) // 设置完整的下载响应头 res.setHeader('Content-Type', 'application/pdf') res.setHeader('Content-Disposition', 'attachment; filename="Employee.pdf"') res.setHeader('Content-Length', pdfBuffer.length) // 直接返回二进制Buffer并结束响应 res.end(pdfBuffer) } export default handler
调用说明
前端不需要对该接口做特殊的fetch解析,直接通过以下任意一种方式调用即可触发浏览器下载:
- 用
window.open('/api/你的路由路径')直接打开接口地址 - 给a标签设置
href为接口地址,加上download属性,点击即可下载
你控制台打印的Buffer开头字节为25 50 44 46,对应ASCII字符%PDF,说明生成的Buffer本身是合法的PDF文件,修复上述问题后即可正常下载打开。
内容的提问来源于stack exchange,提问作者ValenciaHQ
相关产品推荐
相关产品推荐

