ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-08-06 17:00:31  阅读:167  来源: 互联网

标签:canvas vue const lib var pdf


一,安装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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有