Next.js使用Puppeteer生成PDF下载时返回Unexpected token %报错如何解决
报错原因
- 核心错误是前端代码强制将返回的PDF二进制流按JSON格式解析:后端返回的PDF内容开头是
%PDF-1.4,%字符不符合JSON格式规范,调用pdfCall.json()时直接抛出语法错误。 - 额外错误:
fetchAPI本身不支持responseType配置项,该项是XMLHttpRequest的专属属性,写在fetch配置中不会生效,无法按预期获取二进制数据。
解决方法
后端修改
需要给PDF响应添加正确的响应头,同时补充错误处理逻辑,仅在报错时返回JSON格式的错误信息:
import puppeteer from 'puppeteer' async function printPdf(req, res) { const browser = await puppeteer.launch() const page = await browser.newPage() await page.goto(`http://localhost:3000/real-estate-pdf/${req.body.slug}`, { waitUntil: 'networkidle2', }) // 不需要服务器本地存PDF的话可以删除path参数 const pdf = await page.pdf({ printBackground: true, format: 'a4', }) await browser.close() return pdf } async function generatePdf(req, res) { try { const pdf = await printPdf(req, res) // 添加PDF响应头 res.setHeader('Content-Type', 'application/pdf') res.setHeader('Content-Length', pdf.length) res.send(pdf) } catch (err) { // 仅错误时返回JSON格式 res.status(500).json({ error: err.message }) } } export default generatePdf
前端修改
删除fetch中无效的responseType配置,先判断响应状态,成功时按二进制流解析,报错时才解析JSON错误信息:
const create = async () => { try { const pdfCall = await fetch('/api/pdf', { body: JSON.stringify({ slug: fileName.split('.')[0], }), headers: { "Content-Type": "application/json" }, method: 'POST', }) // 错误状态才解析JSON if (!pdfCall.ok) { const { error } = await pdfCall.json() console.log('error: ' + error) return } // 成功响应转arrayBuffer再转base64,适配你已有的下载函数 const arrayBuffer = await pdfCall.arrayBuffer() const base64Pdf = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer))) clientPdfDownload(base64Pdf) } catch (err) { console.error('请求异常:', err) } }
你原本写的base64ToArrayBuffer和clientPdfDownload函数不需要修改,调整后即可正常触发PDF自动下载。
内容的提问来源于stack exchange,提问作者Rus
相关产品推荐
相关产品推荐

