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