Vue實現(xiàn)向PDF文件中添加二維碼
前言
這兩天剛看到一個需求,簡單描述一下,就是我們拿到一個pdf文件流(文件流可以是后端返回的,也可以是從自己本地選的)和一個url鏈接 ,現(xiàn)在要將url鏈接生成二維碼,并將這個二維碼添加到這個pdf文件中,然后再預覽或者下載這個pdf文件。
靈感出自于我之前寫過一篇Vue使用pdf-lib為文件流添加水印并預覽,上篇寫的是在pdf上加水印,其中一種方式就是通過圖片的方式添加上去的,所以這次添加二維碼基本差不多一個意思,我們可以先通過url鏈接生成一個二維碼,這個二維碼其實是個dom元素的,我們使用html2canvas庫可以將二維碼這個dom轉(zhuǎn)為一個canvas對象,有了canvas是不是可以獲取到Blob對象了?有了blob就可以獲取到buffer了,那我們就可以將這個二維碼以圖片的形式嵌入到pdf文件流中。
共用到三個庫分別是:html2canvas 、qrcodejs2-fixes、pdf-lib。
注意這里生成二維碼共有兩個庫,一個是qrcodejs2,這個由于兼容性問題只支持vue2,我這里的例子是用vue3來演示的,所以就是用第二個:qrcodejs2-fixes,這個使用跟qrcodejs2一樣,區(qū)別就是一個適用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'封裝
這里單獨封裝一個方法,用的時候直接調(diào)用該方法,將pdf文件流(blob對象)和二維碼url鏈接地址傳入進去 就可以,我這里就以window打開一個新頁簽預覽處理之后的pdf為例了,真實項目也可能是下載,都是差不多的,下載也很簡單,通過a標簽,window.URL.createObjectURL轉(zhuǎn)為一個路徑,然后給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, // 距離右側(cè)100
y: height - 100, // 距離上側(cè)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)
}封裝的方法中的二維碼樣式啥的,我也懶得動態(tài)設置參數(shù)傳入了,大家有需要在封裝的方法中按需修改即可
引入調(diào)用使用的時候:
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的鏈接為例的,所以掃出來也是百度的鏈接
到此這篇關(guān)于Vue實現(xiàn)向PDF文件中添加二維碼的文章就介紹到這了,更多相關(guān)Vue PDF添加二維碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue-cli和v-charts實現(xiàn)可視化圖表過程解析
這篇文章主要介紹了vue-cli和v-charts實現(xiàn)可視化圖表過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-10-10
vue+axios實現(xiàn)文件下載及vue中使用axios的實例
這篇文章主要介紹了vue+axios實現(xiàn)文件下載及vue中使用axios的實例,需要的朋友可以參考下2018-09-09
Vue2中Element?DatePicker組件設置默認日期及控制日期范圍
后臺項目想使用時間選擇器選擇一段時間進行數(shù)據(jù)篩選,所以下面這篇文章主要給大家介紹了關(guān)于Vue2中Element?DatePicker組件設置默認日期及控制日期范圍的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-11-11
vuex中store存儲store.commit和store.dispatch的用法
這篇文章主要介紹了vuex中store存儲store.commit和store.dispatch的用法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07
Vue實現(xiàn)組件通信的8種實戰(zhàn)方案詳解
組件與組件之間的數(shù)據(jù)傳遞組件的數(shù)據(jù)是獨立的,無法直接訪問其他組件的數(shù)據(jù),通過組件通信,可以訪問其他組件的數(shù)據(jù),本文給大家介紹了Vue實現(xiàn)組件通信的8種實戰(zhàn)方案,需要的朋友可以參考下2025-08-08
淺談vue 組件中的setInterval方法和window的不同
這篇文章主要介紹了淺談vue 組件中的setInterval方法和window的不同,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07

