AWS上用Puppeteer的page.pdf()报错:ReadableStream未定义
问题:Node 18 + Puppeteer 22.3.0 AWS生产环境PDF下载报错
ReferenceError: ReadableStream is not defined 背景
- 本地Node 18环境运行Puppeteer 22.3.0实现的PDF下载功能完全正常
- 部署到AWS生产环境后,调用PDF下载API返回
ReferenceError: ReadableStream is not defined错误
错误栈
error: ReferenceError: ReadableStream is not defined at getReadableFromProtocolStream (/var/www/max-scaffolds/backend/node_modules/puppeteer-core/lib/cjs/puppeteer/common/util.js:241:5) at CdpPage.createPDFStream (/var/www/max-scaffolds/backend/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/Page.js:845:66) at processTicksAndRejections (node:internal/process/task_queues:96:5) at async CdpPage.pdf (/var/www/max-scaffolds/backend/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/Page.js:849:26)
相关代码
public getReportPdf = async(req: Request, res: Response) =>{ const browser = await puppeteer.launch(); const page = await browser.newPage(); try { const { reportId } = req.params; const reportData = await this.reportRepo.getJobAndTemplateWithReport(reportId); const htmlData = await ejs.renderFile('src/helper/templates/report.ejs', { record: reportData[0], reportOverview: REPORT_OVERVIEW }); const image = await getBase64Image('https://maxscaffold-front-stg.taskgrids.com/assets/images/Max-Builders-Default.png') // Need to pass here companyLogo url await page.setContent(htmlData); const pdfBuffer = await page.pdf({ displayHeaderFooter: true, headerTemplate: ` < div style = "font-size: 10px; display: flex; justify-content: center; align-items: center; margin-left: 300px" > <div > Powered by < /div> <img style="height: 50px; width: auto; margin-left: 5px" src="data:image/png; base64, ${image} "/> </div>`, format: 'A4', printBackground: true, preferCSSPageSize: true, scale: 0.8, margin: { top: '100px', bottom:'50px' } }); await page.close(); await browser.close(); const savepath = `./${STORAGE_BUCKET.DEFAULT}/${reportId}_report.pdf`; fs.writeFile(savepath, pdfBuffer, (err) => { if (err) { console.log('err', err); } }); setTimeout(() => { fs.promises.unlink(savepath); }, 25000); const data = process.env.NODE_URL + `api/images/${reportId}_report.pdf`; return generalResponse(req, res,data, successMessage.REPORT_DISPLAY_SUCCESS, true, responseFlag.SUCCESS); } catch (error) { await page.close(); await browser.close(); return generalResponse(req, res, error, errorMessage.SOMETHING_WRONG, false, responseFlag.ERROR); } };
解决方案
1. 显式全局挂载ReadableStream
Puppeteer 22+版本依赖全局的ReadableStream对象,但部分AWS运行环境(如特定容器镜像、Lambda自定义运行时)中该对象未被默认挂载。在代码入口或该API文件顶部添加以下代码:
如果是ES模块(import语法):
import { ReadableStream } from 'stream/web'; globalThis.ReadableStream = ReadableStream;
如果是CommonJS模块(require语法):
const { ReadableStream } = require('stream/web'); global.ReadableStream = ReadableStream;
2. 验证AWS环境Node版本一致性
- 确认AWS生产环境使用的确实是Node.js 18.x版本,避免容器镜像或运行时配置错误导致版本不符
- 若使用AWS Lambda,检查函数配置的运行时是否为
Node.js 18.x,同时排查是否有自定义环境变量修改了全局对象
3. 降级Puppeteer版本(临时应急方案)
若上述方法无效,可临时降级到Puppeteer 21.x版本,该版本对Node 18的兼容性更稳定,不会强制依赖全局的ReadableStream:
npm install puppeteer@21.11.0
内容的提问来源于stack exchange,提问作者harmil sanghavi
相关产品推荐
相关产品推荐

