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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/329915.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

class_7: C++引用

//1、引用是给变量取别名&#xff0c;定义的时候必须初始化&#xff0c;且指向一个确定的内存空间&#xff1b; //2、引用实质是指针常量&#xff0c;值可以改变&#xff0c;地址不可改变&#xff0c;即不可重复赋值#include <iostream> using namespace std;//1、引用是…

阿赵UE学习笔记——10、Blender材质和绘制网格体

阿赵UE学习笔记目录   大家好&#xff0c;我是阿赵。   之前介绍了虚幻引擎的材质和材质实例。这次来介绍一个比较有趣的内置的Blender材质。   在用Unity的时候&#xff0c;我做过一个多通道混合地表贴图的效果&#xff0c;而要做过一个刷顶点颜色混合地表和水面的效果。…

数学建模--论文

内容来自数学建模BOOM&#xff1a;【快速入门】北海&#xff1a;数模建模基础MATLAB入门论文写作数学模型与算法(推荐数模美赛国赛小白零基础必看教程)_哔哩哔哩_bilibili 目录 一、论文整体模版 1.整体框架 2.示例 二、标题 1.标题主题事项 三、摘要 1.摘要三要素&am…

Linux系统:yum仓库

目录 一、yum 1、yum概述 2、yum仓库 3、yum实现过程原理 二、yum配置文件详解 1、主配置文件 2、yum仓库设置文件 3、yum日志文件 三、yum命令详解 1、查询 1.1 yum list [软件名] 1.2 yum info [软件名] 1.3 yum search <关键词> 1.4 yum provides <关…

无重复字符的最长子串[中等]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给定一个字符串s&#xff0c;请你找出其中不含有重复字符的最长子串的长度。 示例 1: 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是"abc"&#xff0c;所以其长度为3。 示例 2: 输入: s &…

Verilog刷题笔记17

题目&#xff1a; For hardware synthesis, there are two types of always blocks that are relevant: Combinational: always (*) Clocked: always (posedge clk) Clocked always blocks create a blob of combinational logic just like combinational always blocks, but …

el-table中设置第一列为多选框,且多选框动态禁用

给el-table第一列写成以下代码: <el-table-columntype"selection"width"55"></el-table-column> 效果: 多选框动态禁用 el-table中设置了 type"selection"&#xff0c;但是由于部分数据是已经处理过的&#xff0c;不允许选中&…

css-盒子等样式学习

盒子居中&#xff0c;继承外层盒子的宽高 兼容性&#xff08;border-box&#xff09;将边框收到盒子内部 初始化div 不用管box-setting content-box 还原 创建为一个类 &#xff0c;让所有需要还原的类 进行继承 padding 用法表示margin上下左右边距 body 外边距&…

高性价比低功耗高性能蓝牙5.2系统级芯片PHY6230

PHY6230 是一款高性价比低功耗高性能Bluetooth LE 5.2系统级芯片&#xff0c;集成32-bit高性能低功耗MCU&#xff0c;16KB OTP&#xff0c;8KB Retention SRAM和64KB ROM&#xff0c;可选EEPROM。内置高性能多模射频收发机最大发射功率10dBm&#xff0c;BLE 1Mbps速率下接收灵敏…

最新 生成pdf文字和表格

生成pdf文字和表格 先看效果 介绍 java项目&#xff0c;使用apache的pdfbox工具&#xff0c;可分页&#xff0c;自定义列 依赖 <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.22<…

5-微信小程序语法参考

1. 数据绑定 官网传送门 WXML 中的动态数据均来自对应 Page 的 data。 数据绑定使用 Mustache 语法&#xff08;双大括号&#xff09;将变量包起来 ts Page({data: {info: hello wechart!,msgList: [{ msg: hello }, { msg: wechart }]}, })WXML <view class"vie…

Nodejs 第三十二章(数据库)

MySQL是一种开源的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它是最受欢迎的数据库系统之一。MySQL广泛用于Web应用程序和其他需要可靠数据存储的应用程序中。 以下是MySQL数据库的一些重要特点和概念&#xff1a; 数据库&#xff1a;MySQL是一个数据库…

Oracle21C + PLSQL Developer 15 + Oracle客户端21安装配置完整图文版

一、Oracle21C PLSQL Developer 15 Oracle客户端文件下载 1、Oracl21C下载地址&#xff1a;Database Software Downloads | Oracle 中国 2、 PLSQL Developer 15下载地址&#xff1a;Registered download PL/SQL Developer - Allround Automations 3、 Oracle 客户端下载地址…

【linux驱动】用户空间程序与内核模块交互-- IOCTL和Netlink

创建自定义的IOCTL&#xff08;输入/输出控制&#xff09;或Netlink命令以便用户空间程序与内核模块交互涉及几个步骤。这里将分别介绍这两种方法。 一、IOCTL 方法 1. 定义IOCTL命令 在内核模块中&#xff0c;需要使用宏定义你的IOCTL命令。通常情况下&#xff0c;IOCTL命令…

RHCE9学习指南 第21章 用bash写脚本

grep的用法是&#xff1a; grep 关键字 file 意思是从file中过滤出含有关键字的行。 例如&#xff0c;grep root /var/log/messages&#xff0c;意思是从/var/log/messages中过滤出含有root的行。这里很明确的是过滤含有“root”的行。 如果我要是想在/var/log/messages中过滤…

IPv6自动隧道---6to4隧道

IPv6 over IPv4自动隧道特点 由于IPv4兼容IPv6隧道要求每一个主机都要有一个合法的IP地址,而且通讯的主机要支持双栈、支持IPv4兼容IPv6隧道,不适合大面积部署。目前该技术已经被6to4隧道所代替。 6to4隧道 集手动隧道和自动隧道的优点于一身,提出6to4的目的是为IPv4网络…

git 常规操作及设置

git 常规操作及设置 Git是一个分布式版本控制系统&#xff0c;可以用来跟踪文件的修改历史并与其他人进行协作开发。下面是一些常见的Git操作及设置&#xff1a; 初始化仓库&#xff1a;使用命令git init在当前目录创建一个新的Git仓库。 克隆仓库&#xff1a;使用命令git clo…

web terminal - 如何在mac os上运行gotty

gotty可以让你使用web terminal的方式与环境进行交互&#xff0c;实现终端效果 假设你已经配置好了go环境&#xff0c;首先使用go get github.com/yudai/gotty命令获取可执行文件&#xff0c;默认会安装在$GOPATH/bin这个目录下&#xff0c;注意如果你的go版本比较高&#xff…

【elementUI】el-select相关问题

官方使用DEMO <template><el-select v-model"value" placeholder"请选择"><el-optionv-for"item in options":key"item.value":label"item.label":value"item.value"></el-option></…

CTF CRYPTO 密码学-4

题目名称&#xff1a;奇怪的先生 题目描述&#xff1a; 描述:oss先生将三个培根的中间一只移到了左边,然后咬了一小口最后一根&#xff0c;说真好吃&#xff0c;真是个奇怪的先生&#xff01; 密文&#xff1a;VlM5WnlXc0ZibEhmMmE1ZHYxMDlhVkdmMlk5WmtRPT0 分析 应该是根据题…