背景:vue3展示给定pdf的url,把第一页转换成图片,无法运行各种报错。根据网上搜索到的文章和文心一言问了半天处理方法都不行,最后翻看PDF.JS官方文档得以解决,现记录。
1.版本问题,网络上搜索到的文章基本上都是很久之前的方法,新版本做了大幅度更新导致各种不兼容,建议使用2.2.228版本。
2.报错Error: No “GlobalWorkerOptions.workerSrc“ specified.
pdfjs工作的时候必须要先指定GlobalWorkerOptions.workerSrc
3.报错TypeError: Cannot set properties of undefined (setting 'workerSrc')
一开始搜到的办法都是
import * as pdfjsLib from 'pdfjs-dist';
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry';
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;
或者是
import * as pdfjsLib from 'pdfjs-dist';
const pdfJS = require('pdfjs-dist')
pdfJS.GlobalWorkerOptions.workerSrc = require('pdfjs-dist/build/pdf.worker.entry')
又或者是
import * as pdfjsLib from 'pdfjs-dist';
pdfjsLib.GlobalWorkerOptions.workerSrc = '../../../node_modules/pdfjs-dist/build/pdf.worker.mjs';
报错TypeError: Cannot set properties of undefined (setting 'workerSrc')
以上方法全都用不了,读取js文件的时候都会失败。因为某些原因无法直接从node_modules文件夹里直接读取js文件,所以必须拿出来放到项目文件里调用。正确的代码如下
import * as pdfjsLib from 'pdfjs-dist';
pdfjsLib.GlobalWorkerOptions.workerSrc = '/js/pdf.worker.min.js';
指定一个项目内的路径比如public之类的文件夹,把下载到的node_modules\pdfjs-dist\build里的pdf.worker.js或者pdf.worker.min.js都行(min就是压缩版本)拿到项目的public/js文件夹里用
不要使用pdf.worker.entry,读不到
4.报错TypeError: Promise.withResolvers is not a function
因为在读取promise的时候还没加载出来,要用异步函数嵌套保证读取的时候promise已经加载了
网上搜到的代码一般都是
const loadingTask = pdfjsLib.getDocument(this.pdfUrl);
const pdf = await loadingTask.promise;
const page = await pdf.getPage(1); // Get the first page
这样不行,promise还是没加载到。
改成如下就不会报错了
loadingTask.promise.then(function(pdf) {
renderPdfPage(pdf, pageNumber); // 现在可以安全地传递 pdf 对象
});
5.page和viewport读空体报错
同理,因为读viewport的时候page没加载出来
pdf.getPage(1).then(async function (page) {
const scale = 1.5;
const viewport = page.getViewport({scale: scale,});
这样写就保证加载了
6.完整的代码如下
<template>
<div>
<div ref="pdfContainer" class="pdf-container" v-if="!imageDataUrl"></div>
<div v-if="imageDataUrl">
<img :src="imageDataUrl" alt="PDF Page as Image" />
</div>
</div>
</template>
<script>
import { ref, onMounted, defineProps } from 'vue';
import * as pdfjsLib from 'pdfjs-dist';
export default {
name: 'PdfToImage',
props: {
pdfUrl: {
type: String,
required: true,
},
pageNumber: {
type: Number,
default: 1,
},
},
setup(props) {
const pdfContainer = ref(null);
const imageDataUrl = ref(null);
const renderPdfPage = async (pdf, pageNumber) => {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
pdf.getPage(1).then(async function (page) {
const scale = 1.5;
const viewport = page.getViewport({scale: scale,});
canvas.width = viewport.width;
canvas.height = viewport.height;
canvas.style.width = Math.floor(viewport.width*0.62) + "px";
canvas.style.height = Math.floor(viewport.height*0.62) + "px";
const renderContext = {
canvasContext: context,
viewport: viewport,
};
await page.render(renderContext).promise;
pdfContainer.value.appendChild(canvas);
});
};
const loadPdf = async (url, pageNumber) => {
const loadingTask = pdfjsLib.getDocument(url);
try {
loadingTask.promise.then(function(pdf) {
renderPdfPage(pdf, pageNumber); // 现在可以安全地传递 pdf 对象
});
} catch (error) {
console.error('Error loading PDF:', error);
}
};
onMounted(() => {
pdfjsLib.GlobalWorkerOptions.workerSrc = '/js/pdf.worker.min.js';
loadPdf(props.pdfUrl, props.pageNumber);
});
// Expose necessary reactive variables to the template
return {
pdfContainer,
imageDataUrl,
};
},
};
</script>
<style scoped>
.pdf-container {
}
</style>
默认读取pdf的第一页,需要改的话把getPage里的数值改成传入的。需要读取多页就改成for循环
在需要用的地方这样调用这个组件就行,把pdf的url传进去
<PdfToImage :pdfUrl="pdfUrl" :pageNumber="1" class=""/>

9082

被折叠的 条评论
为什么被折叠?



