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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:01:10