使用pdfjs加载多页pdf并实现打印
版本:
vue:2.7.10
pdfjs-dist:2.14.305
worker-loader:3.0.1
安装pdfjs-dist、worker-loader
npm install pdfjs-dist@2.14.305 --save
npm install worker-loader@3.0.1 --save-dev
在vue.config.js中配置
// webpack配置
chainWebpack(config) {
// 其余配置......
// 处理 pdf.worker.js 文件
config.module
.rule('worker')
.test(/\.worker\.js$/)
.use('worker-loader')
.loader('worker-loader')
.options({
esModule: false, // 禁用 esModule
})
.end();
},
// 这个得配置上
transpileDependencies: [
'pdfjs-dist'
]
在.vue文件中使用
// 模版部分,对话框内的dom结构
<div id="printArea" ref="printArea" />
// 这里需要注意:"pdfjs-dist": "^2.14.305",版本使用 的是 CommonJS 模块,使用 import 可能无法正常工作
// js部分
const pdfjsLib = require('pdfjs-dist')
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.14.305/pdf.worker.min.js'
// url是pdf的线上路径地址, pdfContainer是dom容器
async renderPDF(url, pdfContainer) {
if (!pdfContainer || !url) return
// 使用 PDF.js 加载 PDF 文件
const pdf = await pdfjsLib.getDocument(url).promise
for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
const page = await pdf.getPage(pageNum)
const viewport = page.getViewport({ scale: 1 })
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
canvas.height = viewport.height
canvas.width = viewport.width
await page.render({
canvasContext: context,
viewport: viewport
}).promise
// canvas标签调用print可能会出现打印内容为空白的问题,因为浏览器的 window.print() 函数在处理 HTML 元素上的 canvas 图像数据时不够完善。
// 因此需要将 canvas 转换为可打印的 HTML 或将 canvas 数据保存为图像后再打印
const imageUrl = canvas.toDataURL('image/png')
const img = document.createElement('img')
img.src = imageUrl
img.style.width = '100%' // 设置图片宽度
pdfContainer.appendChild(img)
}
}
// 打印
onPrintFiles() {
const printArea = this.$refs.printArea
const printWindow = window.open('', '_blank')
printWindow.document.write('<html><head><title>批量打印</title></head><body>')
printWindow.document.write(printArea.innerHTML)
printWindow.document.write('</body></html>')
printWindow.document.close()
printWindow.print()
printWindow.close()
}
// 包装数据、显示对话框、加载文件
// 批量打印图片和pdf文件
async showPrintsDialog() {
this.printFiles = []
for (const key in this.formFile) {
if (this.formFile.hasOwnProperty(key) && this.formFile[key]) {
this.printFiles.push(this.formFile[key])
}
}
if (this.printFiles.length) {
this.printsView = true // 显示对话框
this.$nextTick(() => {
// 获取打印区域元素
const printArea = document.getElementById('printArea')
// 加载并显示所有文件
this.printFiles.forEach(file => {
const fileContainer = document.createElement('div')
fileContainer.className = 'file-container'
const index = file.lastIndexOf('.')
const ext = file.substring(index + 1).toUpperCase()
const isIMG = ['JPEG', 'JPG', 'PNG', 'SVG', 'GIF'].includes(ext)
const isPDF = ['PDF'].includes(ext)
if (isIMG) {
// 图片文件
const img = document.createElement('img')
img.src = file
img.style.width = '100%' // 设置图片宽度
fileContainer.appendChild(img)
} else if (isPDF) {
// PDF 文件
this.renderPDF(file, fileContainer)
}
printArea.appendChild(fileContainer)
})
})
}
}
需要注意的点:
vue
版本不同使用的pdfjs-dist
版本也不同,配置也不同,处理也不同,引入方式也不同(CommonJS/ES Modules)
,需要你自己去看pdfjs-dist
源码包,看是.js
文件还是.mjs
文件,不同文件webpack配置也不一样,所以自己去摸索吧,经过无数次报错就知道了- 该文章仅仅作为记录