Skip to content

Form 导出PDF

js
import { PDFDocument } from 'pdf-lib'
import fontkit from '@pdf-lib/fontkit'

const FONTS = [
  '/file/fangsong_GB2312_0.ttf'
]
const FONT = FONTS[0]
/**
 * pdf form导出pdf
 * @param {*} templatePath fetch url `/file/form.pdf`
 * @param {*} outputName 导出名
 * @param {*} data 表单 {"姓名": "张三"}
 * @param {*} imgs 图片 {"avatar": "http://..."}
 */
export async function fillPDFForm(templatePath, outputName, data, imgs = []) {
  // 加载现有的 PDF 模板
  const templateBytes = await fetch(templatePath).then((res) => res.arrayBuffer())
  const pdfDoc = await PDFDocument.load(templateBytes)
  // 注册自定义字体模块
  pdfDoc.registerFontkit(fontkit)
  const fontBytes = await fetch(FONT).then((res) => res.arrayBuffer())
  const font = await pdfDoc.embedFont(fontBytes)
  // 填写 PDF 表单字段
  const form = pdfDoc.getForm()
  for (const fieldKey in data) {
    const field = form.getTextField(fieldKey)
    if (field) {
      field.setText(data[fieldKey])
      field.updateAppearances(font)
    }
  }
  // 插入头像(图片)
  for (const fieldKey in imgs) {
    const field = form.getButton(fieldKey)
    if (field) {
      if (typeof imgs[fieldKey] === 'string') { // 是图片url
        const emblemUrl = imgs[fieldKey]
        const emblemImageBytes = await fetch(emblemUrl).then(res => res.arrayBuffer())
        const emblemImage = await pdfDoc.embedPng(emblemImageBytes)
        field.setImage(emblemImage)
      } else { // 是图片ArrayBuffer
        const emblemImage = await pdfDoc.embedPng(imgs[fieldKey])
        field.setImage(emblemImage)
      }
    }
  }
  // 只读模式
  form.flatten()
  // 保存 PDF 文件
  const pdfBytes = await pdfDoc.save()
  const blob = new Blob([pdfBytes], { type: 'application/pdf' })
  const link = document.createElement('a')
  link.href = URL.createObjectURL(blob)
  link.download = `${outputName}.pdf`
  link.click()
}

Word模板 导出PDF

目前浏览器端无法直接实现转换

解决方案

既然直接转无法实现,那就采用迂回战术

  1. 先转成 html(用到库 docx-preview
  2. 再将 html 转成 canvas(用到库 html2canvas
  3. 最后将 canvas 转成 png