NodeJS+Express+PDFKit+node-qrcode生成PDF时二维码无法显示
问题根因
二维码无法显示是异步执行顺序错误导致的:
QRCode.toDataURL是异步方法,传入的回调函数会在二维码Base64数据生成完成后才触发执行- 原有代码在调用
QRCode.toDataURL后立刻执行了doc.end(),此时二维码还未生成完成,doc.image()插入图片的逻辑还没运行,PDF文档就已经被关闭写入,自然不会显示二维码 doc.text()、doc.circle()都是同步执行的API,会在doc.end()调用前完成渲染,因此可以正常显示在PDF中
修复方案
方案1:将文档关闭逻辑移到二维码生成回调内
确保二维码成功插入PDF后,再结束文档流,修正后的核心代码如下:
const doc = new PDFDocument({ margin: 0, size: 'LETTER' }) doc.pipe(fs.createWriteStream('/files/result.pdf')) doc.pipe(res) const opts = { errorCorrectionLevel: 'H', type: 'image/png', quality: 0.9, margin: 1, color: { dark:"#000000", light:"#FFFFFF" } } QRCode.toDataURL('http://link.to.website', function (err, url) { if (err) throw err doc.image(url, 50, 45, { width: 50 }) // 所有内容绘制完成后再关闭PDF doc.end() })
方案2:用async/await改写为顺序执行逻辑
如果后续还有其他异步插入的内容,可以把二维码生成方法包装为Promise,用async/await控制执行顺序,避免回调嵌套:
// 包装二维码生成方法为Promise const getQRCodeDataURL = (content, options) => { return new Promise((resolve, reject) => { QRCode.toDataURL(content, options, (err, dataUrl) => { if (err) return reject(err) resolve(dataUrl) }) }) } // PDF生成主逻辑 const createPDF = async () => { const doc = new PDFDocument({ margin: 0, size: 'LETTER' }) doc.pipe(fs.createWriteStream('/files/result.pdf')) doc.pipe(res) const qrOptions = { errorCorrectionLevel: 'H', type: 'image/png', quality: 0.9, margin: 1, color: { dark:"#000000", light:"#FFFFFF" } } // 等待二维码生成完成后再插入PDF const qrDataUrl = await getQRCodeDataURL('http://link.to.website', qrOptions) doc.image(qrDataUrl, 50, 45, { width: 50 }) // 所有内容绘制完毕后关闭文档 doc.end() } createPDF()
提示:所有异步往PDF插入内容的操作(比如加载网络图片、读取本地文件),都需要等待操作完成、内容成功绘制到文档后,再调用
doc.end(),否则都会出现对应内容丢失的问题。
内容的提问来源于stack exchange,提问作者Eirik Madland
相关产品推荐
相关产品推荐

