Node.js+PDFKit从Firebase生成PDF时写入图片遇stream.push() after EOF错误
解决PDF生成时的
stream.push() after EOF错误(Firebase图片写入问题) 我帮你分析下这个问题哈,你遇到的Error: stream.push() after EOF本质是PDF文档的输出流已经关闭,但还有图片写入操作在尝试向流中推送数据,所以触发了这个错误。核心问题是你的代码里异步操作没有被正确等待,导致PDF生成流程和图片请求/写入的节奏乱了。
问题出在哪?
你的代码里有两个关键的异步坑:
forEach遍历Firebase的querySnapshot时,forEach本身不支持异步等待,里面的axios.get是异步任务,循环会直接走完,完全不等图片请求和写入完成;axios.get用了.then回调但没配合await,导致图片数据还没拿到,后续的PDF操作甚至可能已经把文档流关闭了,这时候再执行pdf_doc.image()就会往已经关闭的流里写数据,触发EOF错误。
解决方案
调整代码的异步逻辑,确保所有异步操作都按顺序完成后再继续PDF的生成流程:
- 把
forEach换成for...of循环,因为for...of支持异步等待,能保证每一个文档的处理都完成后再处理下一个; - 对
axios.get请求添加await,确保图片数据完全获取后再写入PDF; - 把所有嵌套的
.then回调改成await写法,让代码的执行顺序更清晰。
修改后的代码示例
// 主函数 async function getPDF() { // ... 其他代码 ... // 处理Firebase数据和图片写入的部分 const querySnapshot = await questionNumber.get(); let i = 0; // 用for...of替代forEach,支持异步等待 for (const doc of querySnapshot.docs) { i++; const exteriorQuestionsData = doc.data(); const exteriorImages = extFormDataAnswers[i-11]?.exteriorQuestionsImages; // 先判断数组是否存在且不为空 if (exteriorImages && exteriorImages.length > 0) { // 遍历图片数组,同样用for...of保证顺序 for (const imgItem of exteriorImages) { const img_url = imgItem.uri; // await等待图片请求完成 const response = await axios.get(img_url, { responseType: 'arraybuffer' }); const my_img = Buffer.from(response.data); // 图片写入PDF的操作要在await之后,确保数据已就绪 pdf_doc.image(my_img, { fit: [300, 300] }) .fontSize(18) .fillColor('#426998') .font('Helvetica-Bold') .moveDown(0.2) .lineWidth(0.5); } } } // ... 后续的PDF生成/保存代码 ... }
额外说明
- 我还优化了图片数组的判断逻辑,用
?.可选链和length > 0替代原来的!= undefined || != [](原来的判断有逻辑问题,!= []永远为true); - 所有异步操作都用
await包裹后,能保证PDF的写入操作是严格按顺序执行的,不会出现“流已经关闭但还在写数据”的情况。
内容的提问来源于stack exchange,提问作者Vipin Raj
相关产品推荐
相关产品推荐

