其他分享
首页 > 其他分享> > vue.js3: 用pdf-lib给pdf文件添加中文字体水印(pdf-lib@1.17.1 / vue@3.2.37)

vue.js3: 用pdf-lib给pdf文件添加中文字体水印(pdf-lib@1.17.1 / vue@3.2.37)

作者:互联网

一,安装pdf-lib库:

1,pdf-lib的官网:
https://pdf-lib.js.org/
2,安装pdf-lib
liuhongdi@lhdpc:/data/vue/pdf/image2pdf$ npm install --save pdf-lib
 
added 4 packages in 5s
3,查看已安装的pdf-lib库的版本:
liuhongdi@lhdpc:/data/vue/pdf/image2pdf$ npm list pdf-lib
image2pdf@0.1.0 /data/vue/pdf/image2pdf
└── pdf-lib@1.17.1 
4,安装fontkit,添加中文字体时要用到
liuhongdi@lhdpc:/data/vue/pdf/image2pdf$ npm install --save @pdf-lib/fontkit
 
added 1 package in 3s
5,查看安装的fontkit库的版本:
liuhongdi@lhdpc:/data/vue/pdf/image2pdf$ npm list @pdf-lib/fontkit
image2pdf@0.1.0 /data/vue/pdf/image2pdf
└── @pdf-lib/fontkit@1.1.1

说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

         对应的源码可以访问这里获取: https://github.com/liuhongdi/
         或: https://gitee.com/liuhongdi

说明:作者:刘宏缔 邮箱: 371125307@qq.com

二,使用pdf-lib

1,配置: 创建字体文件夹: public/fonts 把字体文件复制到目录下   说明: 请使用中文的ttf字体或otf字体, 使用ttc字体时会报错   2,js代码:
<template>
  <div>
    <div style="width:800px;margin: auto;">

      <div >
        选择pdf:
        <input type="file" ref="hiddenfile" accept="application/pdf" @change="handlePdf" class="hiddenInput" />
      </div>
      <div style="width:800px;font-size:12px;margin-top:10px;">
        <el-button type="info" @click="downPdf" plain style="width:400px;">保存并下载pdf</el-button>
      </div>
      <div style="width: 800px;margin-top: 20px;">
        <div  v-for="(item,i) in imgFiles" :key="i" :id="`div_${i}`"
              style="width:265px;position: relative;float:left;overflow: hidden;">
          <canvas :id="`pdf_canvas_${item.id}`" style="border: 1px solid #eeeeee;float:left;" ></canvas>
        </div>
      </div>

    </div>
  </div>
</template>

<script>
import * as pdfjs from 'pdfjs-dist'
import * as pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry'
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker

import { degrees, PDFDocument, rgb } from 'pdf-lib'
import fontkit from "@pdf-lib/fontkit";
import {ref} from "vue"

import {ElMessage} from "element-plus";
import { showLoading, hideLoading } from '@/utils/loading'

export default {
  name: "PdfText",
  setup() {
    //pdf转成的图片文件,保存在数组中
    const imgFiles = ref([]);

    //pdf的名字,记录下来
    const pdfName = ref("");

    //加载文件的结果集
    const result = ref("");
    //选择文件的处理
    const handlePdf = (e) => {
      showLoading();
      //hideLoading();
      let filePaths = e.target.files;
      //清空原有缩略图
      if (filePaths.length === 0) {
        //未选择,则返回
        hideLoading();
        return false;
      }
      imgFiles.value.length = 0;

      let file = e.target.files[0];

      pdfName.value = file.name.substring(0, file.name.lastIndexOf("."));

      const reader = new FileReader();
      reader.readAsArrayBuffer(file);
      reader.onload = () => {
        //把读取到的结果集保存到result
        result.value = reader.result;

        const loadingTask = pdfjs.getDocument(reader.result)
        loadingTask.promise.then((pdf) => {

          var pageNum = pdf.numPages;
          console.log("页数:" + pageNum);

          //准备图片
          for (let i = 1; i <= pageNum; i++) {
            let one = {id: i, imgSrc: ''};
            imgFiles.value.push(one);
          }

          let maxHeight = 0;
          //处理
          for (let i = 1; i <= pageNum; i++) {
            pdf.getPage(i).then((page) => {
              const canvas = document.getElementById('pdf_canvas_' + i);
              const ctx = canvas.getContext('2d')
              const viewport = page.getViewport({scale: 1})
              // 画布大小,默认值是width:300px,height:150px
              canvas.height = viewport.height;
              canvas.width = viewport.width;
              //显示为图片的目标宽度
              const destWidth = 263;
              canvas.style.width = destWidth + 'px';
              // 根据pdf每页的宽高比例设置canvas的高度
              let destHeight = destWidth * (viewport.height / viewport.width);
              canvas.style.height = destHeight + 'px';
              page.render({
                canvasContext: ctx,
                viewport,
              });

              //如果目标高度更高,则调整每个canvas的高度,使显示高度统一
              if (destHeight > maxHeight) {
                maxHeight = destHeight;
                for (let i = 0; i < pageNum; i++) {
                  let canvas = document.getElementById('div_' + i);
                  console.log("canvas name:" + 'div_' + i);
                  console.log(canvas);
                  canvas.style.height = maxHeight + 'px';
                }
              }
            })
            //加载完成
          }    // end for
          hideLoading();
        })
      };
    }
    //下载的pdf,下载添加文字水印
    const downPdf = async () => {
      //判断是否选择了pdf文件
      if (imgFiles.value.length <= 0) {
        ElMessage.error("请先选择pdf文件");
        return false;
      }

      const pdfDoc = await PDFDocument.load(result.value);
      const pages = pdfDoc.getPages();

      // 自定义字体挂载
      pdfDoc.registerFontkit(fontkit);
      var defaultFontBuffer = await fetch(
          '/fonts/SourceHanSerifSC-Light.otf',
      ).then(res => res.arrayBuffer());
      const helveticaFont = await pdfDoc.embedFont(defaultFontBuffer);
      //加文本,演示时只加在了第一页
      const firstPage = pages[0]
      const {  height } = firstPage.getSize()
      firstPage.drawText('用js添加的水印文字上线了,测试看会不会显示完整,字号什么的!', {
        x: 5,
        y: height / 2 + 300,
        size: 50,
        font: helveticaFont,
        color: rgb(0.95, 0.1, 0.1),
        rotate: degrees(-45),
        opacity: 0.8,
      })

      const pdfBytes = await pdfDoc.save();
      saveByteArray(pdfName.value + "_" + timeFormat() + '.pdf', pdfBytes);
    }

    //保存pdf并下载
    const saveByteArray = (reportName, byte) => {
      var blob = new Blob([byte], {type: "application/pdf"});
      var link = document.createElement('a');
      link.href = window.URL.createObjectURL(blob);
      var fileName = reportName;
      link.download = fileName;
      link.click();
    };


    //补0
    const add0 = (m) => {
      return m < 10 ? '0' + m : m
    }

    //格式化时间
    const timeFormat = () => {
      var time = new Date();
      var y = time.getFullYear();
      var m = time.getMonth() + 1;
      var d = time.getDate();
      var h = time.getHours();
      var mm = time.getMinutes();
      var s = time.getSeconds();
      let res = y + add0(m) + add0(d) + add0(h) + add0(mm) + add0(s);
      return res;
    }

    return {
      handlePdf,
      downPdf,
      imgFiles,
    }
  }
}
</script>

<style scoped>

</style>

三,测试效果

pdf的效果:  说明:pdf文件体积会变大,应该是同时打包了用到的字体文件的原因

四,查看vue框架的版本: 

liuhongdi@lhdpc:/data/vue/pdf/image2pdf$ npm list vue
child@0.1.0 /data/vue/pdf/image2pdf
├─┬ @vue/cli-plugin-babel@5.0.6
│ └─┬ @vue/babel-preset-app@5.0.6
│   └── vue@3.2.37 deduped
└─┬ vue@3.2.37
  └─┬ @vue/server-renderer@3.2.37
    └── vue@3.2.37 deduped

 

标签:canvas,vue,const,lib,var,pdf
来源: https://www.cnblogs.com/architectforest/p/16557446.html