UNIAPP给PDF添加内容并下载

Lirioing2025/05/17UNIAPPFEVUEUNIAPP

插件选择

选择 pdf-lib 插件,安装插件的字体库 @pdf-lib/fontkit

npm install pdf-lib
npm install @pdf-lib/fontkit

获取PDF文档

import { PDFDocument, rgb } from 'pdf-lib';
import fontkit from '@pdf-lib/fontkit';
// 获取PDF文档
const getPdfDoc = async () => {
	// 获取PDF文档
	const templateUrl = '/static/pdf/template.pdf';
    const pdfResponse = await fetch(templateUrl)
    const pdfBytes = new Uint8Array(await pdfResponse.arrayBuffer())
    const pdfDoc = await PDFDocument.load(pdfBytes)
}

给PDF文档添加文本内容

  1. 可以通过获取PDF的表单,精确地的将表单数据插入到PDF的指定位置

    const fillPdfDoc = (pdfDoc) => {
      const form = pdfDoc.getForm()
      // 获取所有字段,查看表单字段然后根据自己的表单数据,对应的字段插入进去
      const fields = form.getFields()
      fields.forEach(field => {
        console.log('字段名称:', field.getName(), '类型:', field.constructor.name);
      });
      
      const formData = {...}
      // 填充文本字段
      if (formData.name) {
      	form.getTextField('NameField').setText(formData.name);
      }
      // 填充邮箱字段
      if (formData.email) {
        form.getTextField('EmailField').setText(formData.email);
      }
      return await pdfDoc.save();
    }
    
  2. 我这边的pdf文件获取不到表单,就选择了 在指定坐标位置添加文本

    const fillPdfDoc = (pdfDoc) => {
      const pages = pdfDoc.getPages()
      
      // 添加中文字体
      const fontUrl = '/static/font/simsun.otf';
      const fontResponse = await fetch(fontUrl);
      const fontBytes = await fontResponse.arrayBuffer();
      pdfDoc.registerFontkit(fontkit);
      const chineseFont = await pdfDoc.embedFont(fontBytes);
    	
      // 插入图片文件
      const imageUrl = '/static/images/home.png'
      const imageRes = await fetch(imageUrl)
      const imageBytes = await imageRes.arrayBuffer()
      // 嵌入图片到PDF 图片是png格式,这里的方法是embedPng
      const image = await pdfDoc.embedPng(imageBytes); 
    	
      pages.forEach((page, pageIndex) => {
    	page.drawImage(image, {
          x: 130, // 图片的x坐标
          y: 346, // y坐标从页面底部计算
          width: 90, // 图片宽度
          height: 40, // 图片高度
        });
        page.drawText('文本内容', {
          x: 130, // 图片的x坐标
          y: 346, // y坐标从页面底部计算
          size: 10, // 字体大小
          // 使用导入的字体文件能正确展示中文,遇到数字英文展示问题,可以不填font字段,用默认的
          font: chineseFont, 
          // 字体颜色,红色是rgb(1, 0, 0),不是css中的255,范围是0-1
          color: rgb(0, 0, 0) 
        })
        // 如果不知道具体坐标是多少,可以写个算法把画一个网格线出来
        addGridInPdf(page)
      })
      return await pdfDoc.save();
    }
    
    // 给PDF添加网格线
    const addGridInPdf = async (page) => {
      // 添加网格线
      const { width, height } = page.getSize();
      for (let x = 0; x < width; x += 50) {
        page.drawLine({
          start: { x, y: 0 },
          end: { x, y: height },
          thickness: 0.5,
          color: rgb(0.9, 0, 0),
          opacity: 0.5
        });
        
        page.drawText(x.toString(), {
          x: x + 2,
          y: 10,
          size: 8,
          color: rgb(0.9, 0, 0)
        });
      }
      
      for (let y = 0; y < height; y += 50) {
        page.drawLine({
          start: { x: 0, y },
          end: { x: width, y },
          thickness: 0.5,
          color: rgb(0, 0, 0.9),
          opacity: 0.5
        });
        
        page.drawText(y.toString(), {
          x: 2,
          y: y + 4,
          size: 8,
          color: rgb(0, 0, 0.9)
        });
      }
    }
    

下载完成后的PDF文档

const newPdf = await fillPdfDoc(pdfDoc)
downloadPdf(newPdf, 'template.pdf')
// 下载PDF
const downLoadPdf = (pdfBytes, filename) => {
  const blob = new Blob([pdfBytes], { type: 'application/pdf' })
  const url = URL.createObjectURL(blob)
  // #ifdef H5
  localDownloadPdf(pdfBytes, filename) // 浏览器下载,测试用
  // #endif
  uni.downloadFile({
    url: url,
    success: (res) => {
      if (res.statusCode === 200) {
        // 此时把文件上传给后端
      }
    },
    fail: (err) => {
    }
  });
  // 释放内存
  setTimeout(() => {
    URL.revokeObjectURL(url);
  }, 100);
}

// 下载文件到浏览器中
const localDownloadPdf = async (pdfBytes, filename) => {
  try {
    const blob = new Blob([pdfBytes], { type: 'application/pdf' });
    const url = URL.createObjectURL(blob);
    
    const a = document.createElement('a');
    a.href = url;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);

    setTimeout(() => {
      URL.revokeObjectURL(url);
    }, 100);
  } catch (err) {
    uni.showToast({
      title: '本地浏览器文件下载失败',
      icon: 'none'
    })
  }
}
上次更新 2025/12/6 16:52:48