Demo: 实现PDF加水印以及自定义水印样式

实现PDF加水印以及自定义水印样式

在这里插入图片描述

<template>
    <div>
        <button @click="previewHandle">预览</button>
        <button @click="downFileHandle">下载</button>
        <el-input v-model="watermarkText" />
        <el-input v-model.number="watermarkrotate" />
        <iframe id="log_frame" class="log-iframe" frameborder="0" :src="pdfPreviewUrl"></iframe>
    </div>
</template>
  
<script setup>
import {
    ref, reactive, onMounted } from 'vue'
import {
    degrees, PDFDocument, rgb, StandardFonts } from "pdf-lib";
import fontkit from '@pdf-lib/fontkit'

const pdfFileEnd = ref('http://111.229.162.189:8003/file/construction/2024_01_08/三高共管对接接口(5)_14ba6d68.pdf')
const pdfPreviewBlob = ref()
const pdfPreviewUrl = ref('/pdf/web/viewer.html?file=http://111.229.162.189:8003/file/construction/2024_01_08/三高共管对接接口(5)_14ba6d68.pdf')

const watermarkText = ref('2024-01-17') // 水印文字
const watermarkrotate = ref(45) // 水印旋转角度

// PDF 下载
const addWatermark = async (rotate) => {
   
    /*2.获取pdf文件的arrarybuffer文件流
     可请求后台接口返回的base64文件流,然后转成arrayBuffer类型
     可访问前端项目中的本地文件,不能直接访问服务器链接文件,会有跨域问题*/
    try {
   
        // 1.通过url获取pdf文件的arrarybuffer文件流
        const existingPdfBytes = await fetch(pdfFileEnd.value).then((res) => res.arrayBuffer());
        // 2.将arraybuffer数据转成pdf文档
        const pdfDoc = await PDFDocument.load(existingPdfBytes);
        // 3.1  内置字体(不支持中文), 如果水印中不包含中文可直接用内置字体(不支持中文)
        // const fontkitFile = await pdfDoc.embedFont(StandardFonts.Helvetica);
        // 3.2 自定义字体,如不需要使用自定义字体可以将这一段全部注释掉,也不用下载自定义字体文件和自定义字体工具fontkit
        // 将自己下载好的.ttf文件放置项目中,然后访问文件路径(不支持访问本地文件)
        // const fontBytes = await fetch("@/assets/DS-DIGIT.TTF").then((res) => res.arrayBuffer());
        // pdfDoc.registerFontkit(fontkit); // 自定义字体挂载、fontkit为自定义字体注册工具
        // const fontkitFile = await pdfDoc.embedFont(fontBytes);
        //  4. 为每页pdf添加文字水印
        const pages = pdfDoc.getPages();
        for (let i = 0; i < pages.length; i++) {
   
            const noPage = pages[i];
            const {
    width, height } = noPage.getSize();
            for (let i = 0; i < 10; i++) {
   
                for (let j = 0; j < 3; j++) {
   
                    noPage.drawText(watermarkText.value, {
   
                        x: 230 * j + 36,
                        y: (height / 4) * i + 20,
                        size: 20,
                        // font: fontkitFile, //字体(内置/自定义)
                        color: rgb(0.46, 0.53, 0.6),
                        rotate: degrees(rotate),
                        opacity: 0.3,
                    });
                }
            }
        }
        //5. 保存pdf文件的unit64Arrary文件流
        const pdfBytes = await pdfDoc.save();
        pdfPreviewBlob.value = pdfBytes
        // const blob = new Blob([pdfBytes], { type: 'application/pdf' });
        // const url = window.URL.createObjectURL(blob);
        // pdfPreviewUrl.value = '/pdf/web/viewer.html?file=' + url
        // saveByteArray("水印PDF.pdf", pdfBytes);
    } catch (error) {
   
        console.log("文件下载失败!");
    }
}
// 预览文件
const previewHandle = async () => {
   
    console.log(typeof(watermarkrotate.value));
    await addWatermark(watermarkrotate.value)
    const blob = new Blob([pdfPreviewBlob.value], {
    type: 'application/pdf' });
    const url = window.URL.createObjectURL(blob);
    pdfPreviewUrl.value = '/pdf/web/viewer.html?file=' + url
}
// 下载文件
const downFileHandle = () => {
   
    var blob = new Blob([pdfPreviewBlob.value], {
    type: "application/pdf" });
    var link = document.createElement("a");
    link.href = window.URL.createObjectURL(blob);
    link.download = '水印pdf';
    link.click();
}

onMounted(() => {
   
    addWatermark()
})
</script>

<style lang="scss" scoped>
.log-iframe {
   
    width: 800px;
    height: 520px;
}
</style>

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-18 16:40:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-18 16:40:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-01-18 16:40:01       82 阅读
  4. Python语言-面向对象

    2024-01-18 16:40:01       91 阅读

热门阅读

  1. 算法--插值法

    2024-01-18 16:40:01       56 阅读
  2. UnityShader UsePass介绍

    2024-01-18 16:40:01       55 阅读
  3. Vue-组件缓存-keep-alive

    2024-01-18 16:40:01       51 阅读
  4. 边缘计算和联邦学习的联系

    2024-01-18 16:40:01       47 阅读
  5. 边缘计算的挑战和机遇——数据安全与隐私保护

    2024-01-18 16:40:01       61 阅读
  6. 【无标题】

    2024-01-18 16:40:01       53 阅读
  7. 华为:交换机忘记console密码重置

    2024-01-18 16:40:01       178 阅读
  8. SpringBoot异常处理和单元测试

    2024-01-18 16:40:01       57 阅读