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

Express渲染页面后用Puppeteer生成PDF报Unexpected extraInfo错误如何解决

问题解决方法

根本原因

你遇到的报错核心是两个问题共同导致的:

  1. 路由逻辑死循环:你给/:document路由同时绑定了页面渲染和PDF生成两个中间件,PDF生成逻辑内部又用Puppeteer再次请求同一个/:document地址,等于每次请求都会无限递归触发新的相同请求,请求冲突直接抛出Unexpected extraInfo events异常
  2. 代码细节错误: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 06:27:02