使用 puppeteer 从 HTML 生成 PDF
介绍
解决方案!
完毕
介绍
这篇文章真是让人沮丧,我花了好几个小时才找到一个可行的解决方案。我学到了很多东西,但我觉得这不应该花我那么多时间……
无论如何,目标是从 HTML 生成 PDF,然后将其发送回浏览器,以便用户下载。我尝试了很多不同的方法,我的解决方案很可能不是最优雅或最快速的,但管它呢,总之,它有效。
我把这篇文章当作一个可以保存解决方案的地方,以防将来忘记。这样我就知道该去哪里找了。让我们开始实际的解决方案吧。
解决方案!
前端
让我们从前端开始。
const downloadPDF = () => {
fetch('/api/invoices/create-pdf', {
data: {
invoiceDetails,
invoiceSettings,
itemsDetails,
organisationInfos,
otherDetails,
clientDetails
},
method: 'POST'
}).then(res => {
return res
.arrayBuffer()
.then(res => {
const blob = new Blob([res], { type: 'application/pdf' })
saveAs(blob, 'invoice.pdf')
})
.catch(e => alert(e))
})
}
这是完成所有操作的函数。就我而言,我们正在生成发票。
1) 使用 POST 方法获取数据。这部分我们会使用正确的数据生成 PDF 文件,并在服务器上生成。(服务器代码会随后发布)
3)我们得到的响应需要转换为数组缓冲区。
4) 我们使用 new Blob() 构造函数创建一个 Blob(二进制大对象)。该 Blob 接受一个可迭代对象作为第一个参数。注意,我们的响应数组缓冲区是如何被方括号 ( [res] ) 包围的。要创建一个可以作为 PDF 读取的 Blob,数据需要先被迭代成二进制形式(我猜是这样的……)。另外,请注意application/pdf类型。
5)最后,我使用文件保存包中的 saveAs 函数在前端创建文件!
后端
这是后端部分。这里有一个完整的 Express 应用,以及所有东西。我只是向你展示了这个 PDF 问题中两个方法所在的控制器。
module.exports = {
createPDF: async function(req, res, next) {
const content = fs.readFileSync(
path.resolve(__dirname, '../invoices/templates/basic-template.html'),
'utf-8'
)
const browser = await puppeteer.launch({ headless: true })
const page = await browser.newPage()
await page.setContent(content)
const buffer = await page.pdf({
format: 'A4',
printBackground: true,
margin: {
left: '0px',
top: '0px',
right: '0px',
bottom: '0px'
}
})
await browser.close()
res.end(buffer)
}
}
1) 我正在使用Puppeteer将 HTML 内容创建为 PDF。HTML 内容是从我使用readFileSync获取的 HTML 文件中读取的。
2) 我们存储page.pdf()返回的缓冲区数据,并将其返回给前端。这是稍后转换为数组缓冲区的响应。
完毕
嗯,现在看看代码,它看起来确实比我之前尝试解决这个问题时简单多了。我花了将近10个小时才找到一个合适的答案。10个小时!!!!
提醒自己:如果你感到沮丧,就离开电脑,呼吸新鲜空气,稍后再回来……
编码愉快 <3
文章来源:https://dev.to/damcosset/generate-a-pdf-from-html-and-back-on-the-front-5ff5