nodejs后端PDF生成预研方案:DPF模板预填VS 浏览器DPF生成
Author:zhoulujun Date:
PDF后端生成有2种形式,分为
模板生成:适合简单的表单内容DPF生成。只需要提前筹备模板,后端填数据即可
优点:技术简单
缺点:前端样式负责的情况下,无法与前端页面保持一致,且通常无法复用前端页面。
浏览器生成方案
优点:完全复用前端页面组件,与用户所见页面保持一致
缺点: linux部署无头浏览器(如Puppeteer)复杂,而且设计导授权认证等逻辑的改造
DPF模板方案
PDF模板方案又分为2种,分为DPF预填(已有DPF,填充数据)与 PDF模板库生成
DPF预填
最场景就是 PO、PA 在产品层,通过word等工具转出DPF
使⽤Adobe Acrobat DC创建模板
使用Adobe Acrobat DC,创建表单
具体请参看《adobe acrobat pro制作DPF表单模板》
填写DPF表单
有了DPF表单后,就是读取文件,填写表单就可以了
比如可以使用pdf-lib 库
const templateBytes = await fs.promises.readFile(templatePath); const pdfDoc = await PDFDocument.load(templateBytes); const form = pdfDoc.getForm();
demo代码
const { PDFDocument, StandardFonts } = require('pdf-lib'); const fs = require('fs'); const fontkit = require('@pdf-lib/fontkit') let pdfDoc let font async function fillPdfForm(templatePath, outputPath, data) { const templateBytes = await fs.promises.readFile(templatePath); const fontBytes = await fs.promises.readFile('xxx.ttf'); pdfDoc = await PDFDocument.load(templateBytes); pdfDoc.registerFontkit(fontkit); font = await pdfDoc.embedFont(fontBytes); const form = pdfDoc.getForm(); for (const fieldKey in data) { const field = form.getTextField(fieldKey); if (field) { field.setText(data[fieldKey]); field.updateAppearances(font) } } const modifiedPdfBytes = await pdfDoc.save(); await fs.promises.writeFile(outputPath, modifiedPdfBytes); }
这种方案对于开发来说最简单,只需按照表单提供数据即可
DPF模板生成
这种就是在制作前端页面的时候,使用 pdf模板库(好比taro开发小程序,图的就是编译转换),比如
import React from 'react'; import ReactDOM from 'react-dom'; import { PDFViewer,renderToStream } from '@react-pdf/renderer'; const styles = StyleSheet.create({ page: { flexDirection: 'row',backgroundColor: '#E4E4E4' }, section: { margin: 10, padding: 10,} }); const App = () => ( <PDFViewer> <Document> <Page size="A4" style={styles.page}> <View style={styles.section}> <Text>Section #1</Text> </View> <View style={styles.section}> <Text>Section #2</Text> </View> </Page> </Document> </PDFViewer> ); renderToStream(<App />);
具体参看官网
这种模式,也能过做到页面与PDF模板同一套
但是,对于已经开发好了的页面,在来开发,重构成本还是非常大的!
无头浏览器生成PDF
phantomjs已经成为弃子,puppeteer 现在是首选
puppeteer生成PDF
其是和浏览器按Ctrl+P 另存为PDF是一样的
const puppeteer = require('puppeteer'); (async () => { // 启动浏览器 const browser = await puppeteer.launch(); const page = await browser.newPage(); // 设置要生成的网页内容 await page.setContent(` <h1>Hello, World!</h1> <p>This is a sample PDF generated by Puppeteer.</p> `); // 直接打开要截图的网页 //await page.goto(pageUrl) await page.pdf({ path: 'output.pdf', // 输出文件路径 format: 'A4', // 页面大小 }); })();
这个方案看似简单省事,但是需要解决问题也蛮多
登录验证问题
截图表单内容,一般需要登录态才能访问,这个时候可以setCookie 等方式访问。
关键是如何获取cookie?
第二个,可能因为授权问题,业务逻辑层面也需要改变!
Puppeteer安装问题
Puppeteer 在docker 容器里面,一般没意chrome浏览器,这个时候需要手动安装
一般推荐直接使用 本地配置好的镜像,或者使用第三方封装好镜像
Puppeteer网络访问与安全问题
大部分的容器集群一般网络白名单制度,这个时候防火墙层面审批,…………
第二个是Puppeteer 本身 chrome的sandbox问题 越权问题等审核……
总之,这个方向,安全审批层面,……
综合上面4总方案,对于开发者而言,更推荐使用DPF表单模板方案
开发只需要准备数据映射接口即可……
关于DPF的维护层面,交给产品……
参考文章:
通过pdf模板,填充内容,生成pdf文件---JAVA https://www.cnblogs.com/jthr/p/16229784.html
通过pdf模板,填充内容,生成pdf文件---JAVA https://www.cnblogs.com/jthr/p/16229784.html
转载本站文章《nodejs后端PDF生成预研方案:DPF模板预填VS 浏览器DPF生成》,
请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/JS-Server/9447.html