Vue向pdf文件中添加二维码

news2024/11/25 20:31:55

这两天刚看到一个需求,简单描述一下,就是我们拿到一个pdf文件流(文件流可以是后端返回的,也可以是从自己本地选的)和一个url链接 ,现在要将url链接生成二维码,并将这个二维码添加到这个pdf文件中,然后再预览或者下载这个pdf文件。

灵感出自于我之前写过一篇Vue使用pdf-lib为文件流添加水印并预览,上篇写的是在pdf上加水印,其中一种方式就是通过图片的方式添加上去的,所以这次添加二维码基本差不多一个意思,我们可以先通过url链接生成一个二维码,这个二维码其实是个dom元素的,我们使用html2canvas库可以将二维码这个dom转为一个canvas对象,有了canvas是不是可以获取到Blob对象了?有了blob就可以获取到buffer了,那我们就可以将这个二维码以图片的形式嵌入到pdf文件流中。

共用到三个库分别是:html2canvas 、qrcodejs2-fixes、pdf-lib。

注意这里生成二维码共有两个库,一个是qrcodejs2,这个由于兼容性问题只支持vue2,我这里的例子是用vue3来演示的,所以就是用第二个:qrcodejs2-fixes,这个使用跟qrcodejs2一样,区别就是一个适用vue2一个vue3

安装: 

pnpm add html2canvas
pnpm add qrcodejs2-fixes
pnpm add pdf-lib

引入: 

import html2canvas from 'html2canvas'
import QRCode from 'qrcodejs2-fixes'
import { degrees, PDFDocument } from 'pdf-lib'

封装: 

这里单独封装一个方法,用的时候直接调用该方法,将pdf文件流(blob对象)和二维码url链接地址传入进去 就可以,我这里就以window打开一个新页签预览处理之后的pdf为例了,真实项目也可能是下载,都是差不多的,下载也很简单,通过a标签,window.URL.createObjectURL转为一个路径,然后给a标签增加download属性,值为文件名称,click即下载了。这里就没以下载为例 

src/hooks/EmbedQrcodeToPdf.js

import html2canvas from 'html2canvas'
import QRCode from 'qrcodejs2-fixes'
import { degrees, PDFDocument } from 'pdf-lib'

export default function ({ pdfBlob, qrcodeUrl = 'https://www.baidu.com/' }) {
  if(!pdfBlob) return
  pdfBlob.arrayBuffer().then(async buffer => {
    const pdfDoc = await PDFDocument.load(buffer)
    const qrcodeDom = document.createElement('div')
    qrcodeDom.id = 'wft-qrcode'
    document.body.appendChild(qrcodeDom)
    new QRCode(document.getElementById('wft-qrcode'), {
      text: qrcodeUrl,
      width: '128',
      height: '128',
      colorDark: '#000000',
      colorLight: '#ffffff',
      correctLevel: QRCode.CorrectLevel.H,
    })
    html2canvas(document.getElementById('wft-qrcode')).then(canvas => {
      canvas.toBlob(qrcodeBlob => {
        qrcodeBlob.arrayBuffer().then(async qrcodeBuffer => {
          const image = await pdfDoc.embedPng(qrcodeBuffer)
          const dims = image.scale(0.6)
          const pages = pdfDoc.getPages()
          for (let i = 0; i < pages.length; i++) {
            let page = pages[i]
            const { width, height } = page.getSize()
            page.drawImage(image, {
              x: width - 100, // 距离右侧100
              y: height - 100, // 距离上侧100  就是右上角
              width: dims.width,
              height: dims.height,
              rotate: degrees(0)
            })
          }
          const pdfBytes = await pdfDoc.save()
          preView(pdfBytes)
          document.body.removeChild(qrcodeDom)
        })
      }, 'image/png')
    })
  })
}

// 打开新页签预览
function preView(stream, docTitle = '测试PDF') {
  const URL = window.URL || window.webkitURL;
  const href = URL.createObjectURL(new Blob([stream], { type: 'application/pdf;charset=utf-8' }))
  const wo = window.open(href)
  // 设置新打开的页签 document title
  let timer = setInterval(() => {
    if (wo.closed) {
      clearInterval(timer)
    } else {
      wo.document.title = docTitle
    }
  }, 500)
}

封装的方法中的二维码样式啥的,我也懒得动态设置参数传入了,大家有需要在封装的方法中按需修改即可

引入调用使用的时候: 

previewEmbedQrcodeToPdf({
  pdfBlob: file, // 你的文件流
  qrcodeUrl: 'xxxx' // 你的生成二维码的url链接
})

使用案例代码(V3): 

<template>
  <div class="main">
    <input id="fileInp" type="file">
  </div>
</template>
<script setup>
import { onMounted, onUnmounted } from 'vue'
import previewEmbedQrcodeToPdf from '../hooks/EmbedQrcodeToPdf'

let cusInp = null

onMounted(() => {
  cusInp = document.getElementById('fileInp')
  cusInp.addEventListener('input', inpHander)
})

onUnmounted(() => {
  cusInp.removeEventListener('input', inpHander)
})

function inpHander(event) {
  const file = event.target.files[0]
  if(!file) return
  previewEmbedQrcodeToPdf({
    pdfBlob: file
  })
}
</script>
<style scoped>
.main {
  width: 100%;
  height: 100%;
}
</style>

demo效果: 

 

 

右上角这个二维码就是我们生成的,添加到这个pdf中的,我这里是以baidu的链接为例的,所以扫出来也是百度的链接

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一元线性回归分析

一元线性回归分析&#xff1a; &#xff08;1&#xff09;假设X与Y有线性相关关系&#xff0c;求Y与X样本回归直线方程&#xff0c;并求 的无偏估计&#xff1b; &#xff08;2&#xff09;检验Y和X之间的线性关系是否显著(α0.05)&#xff1b; &#xff08;3&#xff09;当Xx0…

通过电脑屏幕传输文件

简介 本文介绍一套用于通过屏幕传输文件信息的软件。 通过屏幕传输文件&#xff0c;即非接触式&#xff0c;非插入式传递文件&#xff0c;是除了常用的网络传输&#xff0c;硬盘类介质拷贝之外的文件信息传输方式&#xff0c;基本原理就是将待传输的文件转换为二维码&#xf…

SkipList(跳表)

基本概述 SkipList&#xff08;跳表&#xff09;首先是链表&#xff0c;但与传统链表相比有几点差异&#xff1a; 元素按照升序排列存储节点可能包含多个指针&#xff0c;指针跨度不同【根据元素个数不同&#xff0c;可以建立多级指针&#xff08;最多可以建立32级指针&#…

liunx优化命令之free命令

free 这里写目录标题 一、free命令描述&#xff1a;1.free命令的语法&#xff1a;2.free命令的选项&#xff1a;3.free命令的输出格式&#xff1a; 二、压力测试工具stress&#xff1a;1.工具简介&#xff1a;2.参数详解&#xff1a;3.下载压力测试工具&#xff1a; 三、模拟实…

基于51单片机设计的红外遥控器

一、项目介绍 遥控器是现代生活中必不可少的电子产品之一,目前市面上的遥控器种类繁多,应用范围广泛。而 NEC 红外遥控器协议则是目前应用最为广泛的一种协议之一,几乎所有的电视、空调等家用电器都支持该协议。 本项目是基于 51 单片机设计支持 NEC 协议的红外遥控器,实…

TPU-MLIR的环境搭建和使用

1、开发环境配置 Linux开发环境 一台安装了Ubuntu16.04/18.04/20.04的x86主机&#xff0c;运行内存建议12GB以上下载SophonSDK开发包(v23.03.01) &#xff08;1&#xff09;解压缩SDK包 sudo apt-get install p7zip sudo apt-get install p7zip-full 7z x Release_<date&…

docker数据管理---数据卷,数据卷容器

在Docker中&#xff0c;数据卷&#xff08;data volumes&#xff09;和数据卷容器&#xff08;data volume containers&#xff09;是用于在容器之间共享和持久化数据的两种不同的机制。 一、数据卷 数据卷是一个特殊的目录或目录&#xff0c;可以绕过容器文件系统的常规层&a…

CSDN 周赛 58 期

CSDN 周赛 58 期 前言1、题目名称&#xff1a;打家劫舍2、题目名称&#xff1a;小Q的鲜榨柠檬汁3、题目名称&#xff1a;收件邮箱4、题目名称&#xff1a;莫名其妙的键盘后记 前言 很多人都知道&#xff0c;CSDN 周赛的题目出自每日一练&#xff0c;甚至连用例都不会变动&…

【一起啃书】《机器学习》第九章 聚类

文章目录 第九章 聚类9.1 聚类任务9.2 性能度量9.2.1 外部指标9.2.2 内部指标 9.3 距离计算9.3.1 欧氏距离9.3.2 曼哈顿距离9.3.3 切比雪夫距离9.3.4 闵可夫斯基距离9.3.5 标准化的欧几里得距离9.3.6 马氏距离9.3.7 兰氏距离9.3.8 余弦距离9.3.9 汉明距离9.3.10 编辑距离 9.4 原…

替换CentOS 6.x系统中 X11图形界面的启动logo

这个属于定制一个系统的logo了。 网上有很多方法&#xff0c;直接修改一个是最简单的了。 看操作&#xff1a; 下载CentOS 的主题&#xff0c;网上自己搜一个喜欢的就行了。 [rootlocalhost Downloads]# tar zxvf vizta-use-it.tar.gz [rootlocalhost Downloads]# cd vizta …

目标检测数据集:红外图像弱小飞机目标检测数据集

✨✨✨✨✨✨目标检测数据集✨✨✨✨✨✨ 本专栏提供各种场景的数据集,主要聚焦:工业缺陷检测数据集、小目标数据集、遥感数据集、红外小目标数据集,该专栏的数据集会在多个专栏进行验证,在多个数据集进行验证mAP涨点明显,尤其是小目标、遮挡物精度提升明显的数据集会在该…

ArduPilot开源代码之AP_VideoTX

ArduPilot开源代码之AP_VideoTX 1. 源由2. AP_VideoTX子模块2.1 AP_VideoTX2.1.1 AP_VideoTX::init2.1.1 AP_VideoTX::update 2.2 AP_Tramp2.2.1 AP_Tramp::init2.2.2 AP_Tramp::update2.2.3 AP_Tramp::process_requests 2.3 AP_SmartAudio2.3.1 AP_SmartAudio::init2.3.2 AP_S…

requests库的使用

文章目录 get 请求post 请求get 请求和 post 请求的区别response1. res.headers2. status_code3. json get 请求 参数类型作用urlstr发起请求的地址params字典url为基准地址&#xff0c;不包含查询参数&#xff1b;使用此参数会自动对 params 字典编码&#xff0c;然后和url拼…

【Spring】@PropertySource 配置文件自定义加密、自定义Yaml文件加载

文章目录 前言参考目录实现步骤1、包结构2、Maven3、自定义配置文件4、application 文件5、自定义数据库配置 MyDataSource6、加密配置 EncryptYamlProperties7、自定义读取yaml配置 MyPropertySourceFactory8、测试加密解密9、自定义 Properties 文件读取10、测试自定义配置读…

走近科学之《JVM 的秘密》

JVM JVM、内存模型、类加载机制、对象的创建、垃圾回收机制、对象内存分配策略、JVM调优等。 1 简介 JVM 即 java 虚拟机&#xff08;Java Virtual Machine&#xff09;&#xff0c;JVM是一种用于计算设备的规范&#xff0c;是一个虚构出来的计算机。是通过在实际计算机上仿真…

msvcr120.dll丢失的解决方法-一键解决提示msvcr120.dll丢失问题

msvcr120.dll是的动态链接库文件之一。它在Windows操作系统中发挥着重要的作用&#xff0c;它提供了应用程序所需的各种功能和方法。 该文件返回编译后的代码所需的支持库。msvcr120.dll包含用于C / C编译器生成的应用程序所需的重要功能&#xff0c;包括数学函数&#xff0c;…

Selenium定位不到元素怎么办?一定要这么做

目录 1、frame/iframe表单嵌套 selenium自动化测试视频教程&#xff1a; 2、页面跳转到新标签页&#xff0c;或弹出警告框等 3、页面元素失去焦点导致脚本运行不稳定 4、使用Xpath或CSS定位 6、元素被遮挡&#xff0c;不可用&#xff0c;不可见 2023最新的Selenium自动化…

linux部署rabbitmq开启mqtt插件由于监听1883端口导致重启rabbitmq失败的解决方法

linux部署rabbitmq开启mqtt插件由于监听1883端口导致重启rabbitmq失败的解决方法 第一步&#xff1a;部署rabbitmq 部署rabbitmq请移步&#xff08;在这里可以找到erlang和rabbitmq适配的版本并下载安装包&#xff09;&#xff1a; https://blog.csdn.net/char1otte/article/de…

mysql:索引原理与慢查询优化

一 索引的原理 1. 索引原理 索引的目的在于提高查询效率&#xff0c;与我们查阅图书所用的目录是一个道理&#xff1a;先定位到章&#xff0c;然后定位到该章下的一个小节&#xff0c;然后找到页数。相似的例子还有&#xff1a;查字典&#xff0c;查火车车次&#xff0c;飞机…

【Shiro】第一章 权限概述

目录 1、什么是权限 2、认证概念 3、授权概念​​​​​​​ 1、什么是权限 权限管理&#xff0c;一般指根据系统设置的安全策略或者安全规则&#xff0c;用户可以访问而且只能访问自己被授权的资源&#xff0c;不多不少。权限管理几乎出现在任何系统里面&#xff0c;只要…