快速选择 PDF 生成工具(纯干货)

53 阅读3分钟

大家好,我是CC,在这里欢迎大家的到来~

“当你的前端项目需要一个PDF生成功能时,面对众多的技术方案,你会如何抉择?是选择看似简单的html2canvas + jspdf组合,还是功能强大但学习曲线稍高的pdfmake,或是其他服务端方案?

这个决策的关键,往往在于对开发体验、样式控制能力、复杂度与性能的权衡。为了找到这个问题的答案,我深入调研和实践了目前主流的前端PDF生成方案。本文将为你进行一次全面的对比分析,并最终阐述为什么在大多数纯前端场景下,pdfmake成为了我的首选推荐。”

方案对比

首先我们对比下各个方案的优劣势。

window.print

获取 body 下内容,触发 window.print 另存为 PDF。

优势

  • 改动小,实现快速

劣势

  • 网页内容会被改变,体验不好
  • 不够高级

jsPDF

创建 PDF 文件,添加元素;也可以将 DOM 节点转 PDF。

优势

  • 掌控写入 PDF 的内容
  • 不会出现分页字被分割的问题

劣势

  • 需要引入字体文件,但由于字体文件过大会导致用户体验差
  • DOM 节点转 PDF 效果差,会丢失大量样式
  • 表格图片变形

html2canvas + jsPDF

将 DOM 节点转化成图片在转化成 PDF。

优势

  • 改动小,实现快

劣势

  • 相当于放了图片在 PDF 里,会失真
  • 在图片超出 PDF 页面大小时缩小展示
  • PDF 可搜索复制功能丢失

pdfmake

创建 PDF 文件,添加元素;结合 html-to-pdfmake 可将 DOM 节点转 PDF。

优势

  • 写入的 PDF 内容可掌控
  • 解决分页截断处理较好

劣势

  • 需要导入字体文件,但由于字体文件过大会导致用户体验差
  • 代码量相对较多

pdfmake使用

步骤

  1. pnpm i pdfmake
  2. 找个想要的字体(字体库) 例如导入字体 NotoSansSC-Regular.ttf
  3. 下载放到 node_modules/examples/fonts
  4. 打开 node_modulespdfmake 文件夹的终端
  5. 运行
node build-vfs.js "./examples/fonts"
  1. 使用
import pdfMake from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';

pdfMake.vfs = pdfFonts.pdfMake.vfs;
pdfMake.fonts = {
  NotoSansSC: {
    normal: `${window.location.origin}/assets/NotoSansSC-Regular.ttf`,
    bold: `${window.location.origin}/assets/NotoSansSC-Bold.ttf`,
  },
};

const docDefinition: any = {
  pageMargins: [ 40, 60, 40, 60 ],
  content, // 写入的内容
  pageSize: 'A4',
  defaultStyle: {
    // 设置定义的字体为默认字体
    font: 'NotoSansSC',
    fontSize: 16,
    bold: true,
  },
  styles: {
    header: {
      background: '#f2f2f2',
      bold: true,
      width: '100%',
      alignment: 'center',
      margin: [ 0, 0, 0, 10 ],
    },
    table: {
      fontSize: 12,
      bold: false,
      margin: [ 0, 0, 0, 10 ],
    },
    sub_title: {
      fontSize: 12,
      bold: false,
      margin: [ 0, 0, 0, 10 ],
    },
    text: {
      fontSize: 12,
      bold: false,
      margin: [ 0, 0, 0, 10 ],
    },
  },
};
// 测试用
// const win = window.open('', '_blank');
// pdfMake.createPdf(docDefinition).open({}, win);

pdfMake.createPdf(docDefinition).download('分析报告', () => {
  this.message.success('下载成功');
});

存在的问题

  1. 字体导入方式存在问题。
  2. 根据文档看 VFS 虚拟文件系统目前(v0.2.8,现已实现)没有实现,Http 协议方式会更加推荐使用。
  3. Http 导入字体,因为字体文件较大且可能会同时使用一个字体的多个文件(像 Regular、Bold),使用体验不好。

优化方式

  1. 在生成 PDF 及下载字体时给用户反馈,表示正在下载中。
  2. 预加载字体文件。
  3. 对字体文件进行过滤,只需要文档中文字对应的内容。

总结

当然 pdfmake 不止这些优势,更多功能大家有业务有需求时去探索探索吧。

pdfmake 地址