Express渲染页面后用Puppeteer生成PDF报Unexpected extraInfo错误如何解决
问题解决方法
根本原因
你遇到的报错核心是两个问题共同导致的:
- 路由逻辑死循环:你给
/:document路由同时绑定了页面渲染和PDF生成两个中间件,PDF生成逻辑内部又用Puppeteer再次请求同一个/:document地址,等于每次请求都会无限递归触发新的相同请求,请求冲突直接抛出Unexpected extraInfo events异常 - 代码细节错误:
res.render异步执行未等待完成就调用next()、重复执行两次browser.close()、Puppeteer启动缺少Linux环境必要参数、版本不匹配也会触发该类报错
修复步骤
1. 拆分路由避免死循环
将页面渲染和PDF生成逻辑拆分到不同路由,防止递归请求:
// 页面渲染路由:仅返回渲染后的HTML页面 router.get('/:document', documentController.getDocument); // PDF生成路由:仅处理PDF导出逻辑 router.get('/print/:document', documentController.printDocument);
2. 修正getDocument中间件
res.render为异步方法,无需在页面渲染路由中调用next(),直接完成响应即可。要实现每个文档对应PDF一页,只需要在渲染模板时给每个文档容器添加page-break-after: always的CSS属性即可自动分页:
exports.getDocument = async (req, res, next) => { try { const course = req.params.document.split('-')[0]; const document = req.params.document.split('-')[1]; const documents = await Document.find({ CODE: course }); res.status(200).render(`${document}`, { title: document, documents, }); } catch (err) { next(err); } };
3. 修正printDocument中间件
去掉重复的关闭浏览器逻辑,添加Puppeteer启动必要参数,完成PDF生成后返回文件给客户端:
exports.printDocument = async (req, res, next) => { let browser; try { const url = req.params.document; browser = await puppeteer.launch({ // 若使用Puppeteer自带的Chromium可删除executablePath配置,避免版本不匹配 // executablePath: '/usr/bin/chromium', args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'] }); const page = await browser.newPage(); // Puppeteer访问纯页面渲染路由,不会触发PDF生成逻辑,避免死循环 await page.goto(`http://localhost:3000/${url}`, { waitUntil: 'networkidle2' }); const pdfPath = path.join(appRoot.path, 'downloads/certificate.pdf'); await page.pdf({ path: pdfPath, format: 'A4', printBackground: true, margin: { top: '1cm', left: '1cm', right: '1cm', bottom: '1cm', }, }); await browser.close(); console.log('pdf generated successfully'); // 返回PDF文件给客户端下载 res.download(pdfPath, 'certificate.pdf', (err) => { if (err) next(err); }); } catch (err) { // 异常时确保浏览器实例关闭,避免内存泄漏 if (browser) await browser.close(); next(err); } };
4. 版本兼容排查
如果修改后仍出现Unexpected extraInfo events报错,直接卸载系统安装的Chromium,使用Puppeteer安装时自动匹配下载的内置Chromium,删除executablePath配置即可,该报错90%以上是Puppeteer和Chromium版本不匹配导致。
内容的提问来源于stack exchange,提问作者Simeon
相关产品推荐
相关产品推荐

