Source: packages/utils/WaterMark2PDF.js

import { PDFDocument } from "pdf-lib"
/**
 *
 * @param {*} url
 * @param {*} config // 中雄机密文件禁止外传 + 名字 + 手机尾号,水印密度和企微差不多就可以
 * @returns {string} 返回处理后的url或者原url
 */
export const addPDFWaterMark = async (url, config = { text: { title:'', subtitle:'中雄机密文件禁止外传' }, size: 20 }) => {
  // 获取文件的 arrayBuffer 流,获取路径可以前端本地项目文件,如果是脚手架,文件需要放在 public 目录下
  const { text, size } = config;
  // 也可以从后台获取返回的 base64 文件流
  const existingPdfBytes = await fetch(url).then(res => res.arrayBuffer())
  try {
    
    // 生成一个 pdf 文档对象
    const pdfDoc = await PDFDocument.load(existingPdfBytes,{ignoreEncryption:true})
    // const pdfDoc = await PDFLib.PDFDocument.load(existingPdfBytes)
    // console.log('existingPdfBytes=======>',existingPdfBytes,pdfDoc); ,parseSpeed:100,capNumbers:true
    // console.log('pdf水印=====================',pdfDoc.isEncrypted, config);
    if (!pdfDoc.isEncrypted) {
      // 生成 canvas 文字图片
      let canvas = document.createElement('canvas')
      const textBlockWidth = 300//size * (text.length + 1)
      const textBlockHeight = 300//size * 4
      // const textBlockWidth = size * (text.length + 1)
      // const textBlockHeight = size * 2
      canvas.width = textBlockWidth
      canvas.height = textBlockHeight
      const ctx = canvas.getContext('2d')
      ctx.fillStyle = 'rgba(24, 22, 22, 0.3)'
      ctx.font = `${size}px Microsoft Yahei`
      ctx.rotate(-20 * Math.PI / 180);
      ctx.fillText(text.title, 0, 60)
      ctx.fillText(text.subtitle, 0, 100)
      // ctx.fillText(text, size / 2, size)
  
      const png = canvas.toDataURL('img/png')
      const imagePDF = await pdfDoc.embedPng(png)
  
  
      // 获取所有的 pdf 页面
      const pages = pdfDoc.getPages()
      for (let i = 0; i < pages.length; i++) {
        const page = pages[i]
        const { height } = page.getSize()
        for (let i = 0; i < 10; i++) {
          for (let j = 0; j < 6; j++) {
            // page.drawText('watermark', {
            //     x: 200 * j,
            //     y: (height / 4) * i,
            //     size: 16,
            //     opacity: 0.3,
            // })
  
            page.drawImage(imagePDF, {
              x: textBlockWidth * j,
              y: (height / 3) * i,
              opacity: 0.5,
            })
          }
        }
      }
      // 生成 unit64Arrary文件流
      const pdfBytes = await pdfDoc.save();
      let blobData = new Blob([pdfBytes], { type: "application/pdf;Base64" });
  
      // 返回一个新的 url 链接
      const tempurl = window.URL.createObjectURL(blobData);
      return tempurl
    }
  } catch (error) {
    console.log('pdf 解析出错:',error)
  }
  return url
}

// https://blog.csdn.net/Ljwen_/article/details/127876863