React组件通过Puppeteer生成PDF为空问题求助
React页面生成空PDF问题排查
场景描述
实现流程:未授权用户进入「申请项目报告」页面提交申请,管理员审批后,NestJS服务器调用Puppeteer容器生成React页面的PDF,再通过Nodemailer发送邮件。当前问题:传入谷歌URL时PDF生成正常,但传入React应用URL时返回空PDF,响应数据显示为data: <Buffer >。
相关代码
NestJS服务器代码
await axios .get(`${PUPPETEER_APP_URL}/pdf`, { responseType: 'arraybuffer', params: { url: programUrl } })
Puppeteer应用代码
路由
app.get('/pdf', async (req, res) => { const url = req.query.url const result = await generatePdf(`${CLOUD_APP_URL}/${url}`) res.contentType('application/pdf'); res.send(result); });
服务
const puppeteer = require('puppeteer'); const generatePdf = async (payload) => { try { const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] }); const page = await browser.newPage(); await page.goto(payload, { waitUntil: ['domcontentloaded', 'networkidle0', 'load'] }) await page.emulateMediaType('screen') const pdf = await page.pdf(); await browser.close(); return pdf; } catch (error) { console.log('GENERATE PDF ERROR :>> ', error); } }; module.exports = generatePdf;
可能的原因及排查步骤
1. React页面异步渲染未完成
虽然设置了waitUntil参数,但React的异步数据请求、组件挂载后的渲染操作可能在domcontentloaded/networkidle0事件之后才完成,导致Puppeteer提前生成PDF。
- 排查方案:
- 等待页面中关键渲染元素加载完成:
// 替换#report-content为页面实际存在的内容容器选择器 await page.waitForSelector('#report-content', { timeout: 10000 }); - 临时添加固定延迟测试(仅用于验证):
await page.waitForTimeout(3000); // 等待3秒确保渲染完成
- 等待页面中关键渲染元素加载完成:
2. Puppeteer无权限访问React页面
React页面可能存在权限校验,Puppeteer访问时未携带认证信息(如Token、Cookie),导致页面跳转到登录页或显示空白。
- 排查方案:
- 打印页面响应内容,确认实际访问结果:
page.on('response', async (response) => { if (response.url() === payload) { console.log('页面响应状态:', response.status()); console.log('页面响应内容:', await response.text()); } }); - 携带必要的认证信息:
// 设置认证请求头 await page.setExtraHTTPHeaders({ 'Authorization': 'Bearer YOUR_AUTH_TOKEN' }); // 或设置Cookie await page.setCookie({ name: 'auth_token', value: 'YOUR_TOKEN', domain: new URL(payload).hostname });
- 打印页面响应内容,确认实际访问结果:
3. 网络连通性或URL格式问题
Puppeteer容器可能无法访问React应用的网络地址,或者URL拼接时出现格式错误(如重复斜杠)。
- 排查方案:
- 在Puppeteer容器内测试网络连通性:
curl -v YOUR_REACT_APP_FULL_URL - 打印拼接后的完整URL,检查格式:
const fullUrl = `${CLOUD_APP_URL}/${url}`; console.log('最终访问URL:', fullUrl);
- 在Puppeteer容器内测试网络连通性:
4. Headless模式兼容性问题
新版Puppeteer的headless: true对应「new headless」模式,可能存在渲染兼容性问题。
- 排查方案:
- 切换为旧版无头模式测试:
const browser = await puppeteer.launch({ headless: 'old', args: ['--no-sandbox', '--disable-setuid-sandbox'] });
- 切换为旧版无头模式测试:
5. CSS样式导致内容隐藏
页面的CSS属性(如display: none、height: 0)可能导致内容在PDF中无法显示。
- 排查方案:
- 生成页面截图,确认实际渲染内容:
await page.screenshot({ path: 'test-screenshot.png' }); - 检查页面容器元素的样式,确保内容可见且有正确的高度。
- 生成页面截图,确认实际渲染内容:
内容的提问来源于stack exchange,提问作者Vyacheslav Fedorin
相关产品推荐
相关产品推荐

