docker 平台 nodejs puppeteer实现html转pdf
1. 背景
pdm系统中有需求工艺单需要打印成pdf(客户对细节要求极高),当时出了5个方案:
- 从dom制作屏幕截图 html2canvas jspdf 文字无法拷贝
- 使用pdf库 jspdf 或 pdfkit 按组件一个一个拼凑,不合适已有html的打印模板方式
- css打印规则,调用浏览器打印,pdf 文件导入到系统,操作繁琐
- itext (目前用的) 和spire功能强大,但商业用途需收费,wkhtmltopdf开源免费,后端生成,黑匣子,后端开发前端代码,可视化麻烦通过模板生成pdf的实际效果和模板效果相差较大,修改起来不好把握
- 基于node.js的puppeteer和headlesschrome 展示效果与实际生成的pdf接近
使用方案5是可以借助puppeteer调用headless浏览器生成pdf,对css的支持度很高,pdf能很大限度反应模板的样式(对css支持度很高),前端对模板的控制度更高,支持dom操作,以下是模板样式和pdf样式对比:
生成的pdf文件样式和编写的html模板样式一致度较高,可以让前端编写模板文件实时查看html内容样式,改完之后用该模板调用后端的node服务生成的pdf模板能较高程度的还原模板内容,前端可以通过模板引擎如ejs(类似于当前方案后端技术的freemarker模板)生成模板执行一些复杂的dom操作和样式控制。
2. 所需依赖
npm install express jsdom puppeteer
express: 用来和业务系统通信,返回pdf流给业务系统
jsdom: 解析dom,在生成pdf的时候要让前端可以自定义pdf的页头页尾
puppeteer: 调用headless生成pdf
3. 核心代码
genpdffile.js
const puppeteer = require('puppeteer'); const fs = require('fs'); const jsdom = require("jsdom"); const { jsdom } = jsdom; let browserinstance; async function getbrowserinstance() { if (!browserinstance) { browserinstance = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] }); } return browserinstance; } async function generatepdffromhtml(htmlstring) { try { // 启动puppeteer const browser = await getbrowserinstance(); const page = await browser.newpage(); // 页眉 let headertemplate = ""; // 页脚 let footertemplate = ""; { // 构建页眉 console.log("headertemplate"); let dom = new jsdom(htmlstring); let document = dom.window.document; const elementstoremove = document.queryselectorall(".page_start"); if(elementstoremove.length > 0) { headertemplate = elementstoremove[0].outerhtml; } elementstoremove.foreach(el => el.parentnode.removechild(el)); updatedhtmlstring = dom.serialize(); } { // 构建页脚 console.log("footertemplate"); dom = new jsdom(updatedhtmlstring); document = dom.window.document; const endelementstoremove = document.queryselectorall(".page_end"); if(endelementstoremove.length > 0) { footertemplate = endelementstoremove[0].outerhtml; } endelementstoremove.foreach(el => el.parentnode.removechild(el)); updatedhtmlstring = dom.serialize(); } // 设置html内容并生成pdf的buffer await page.setcontent(updatedhtmlstring); // 设置 pdf 选项 const pdfoptions = { path: 'example.pdf', format: 'a4', displayheaderfooter: true, headertemplate, footertemplate, margin: { top: '60px', bottom: '20px', left: '20px', right: '50px' }, }; // 生成 pdf // 如果要生成带着 screen media的pdf,在page.pdf() 前面先调用 page.emulatemedia('screen') const pdfbuffer = await page.pdf(pdfoptions); return pdfbuffer; } catch(error) { console.log(error); } } module.exports = { getbrowserinstance, generatepdffromhtml }
4. dockerfile
from ghcr.io/puppeteer/puppeteer:latest maintainer weiqlog@126.com user root run mkdir -p /pdfg workdir /pdfg copy package*.json ./ copy . . run npm instal expose 10030 entrypoint ["node", "main.js", "10030"]
使用:
docker pull 1505774577/html_to_pdf:1.0.0.dev docker run -d -p 10030:10030 --cap-add=sys_admin 1505774577/html_to_pdf:1.0.0.dev
以上就是docker平台下nodejs puppeteer实现html转pdf过程示例的详细内容,更多关于docker 平台 nodejs puppeteer实现html转pdf的资料请关注代码网其它相关文章!
发表评论