需要下载pdfjs-dist
<template><a-modal class="fill-modal" v-model:open="state.visible" :title="state.modalTitle" width="50%" @cancel="handleCancel"><div class="preview-btns-posi"><a-button type="primary" @click="exportBtn" :loading="state.downLoading">下载</a-button><a-button @click="handleCancel" type="primary">返回</a-button></div><div class="interviewVideo_main" id="videoContainer"><!--此处根据pdf的页数动态生成相应数量的canvas画布--><canvas v-show="state.show" v-for="pageIndex in pdfPages" :id="`pdf-canvas-` + pageIndex" :key="pageIndex"style="display: block;width:100%;" class="canvas"></canvas></div><template #footer></template></a-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, nextTick } from "vue";
import * as pdfjsLib from "pdfjs-dist/build/pdf.js";import * as workerSrc from 'pdfjs-dist/build/pdf.worker.min.js'
import { message } from "ant-design-vue";
import { downloadBlobAsync } from "@/lib/tool";let pdfPages = ref(0); // pdf文件的页数
let pdfDoc: any = reactive({})
let pdfScale = ref(1.0); // 缩放比例
const state: any = reactive({visible: false,downLoading: false,modalTitle: '预览文件',show: false
})
const props = defineProps<{file: {previewPath: string,originalFileName: string,path: string,}
}>()//调用loadFile方法
//获取pdf文档流与pdf文件的页数
const loadFile = async (url: string) => {try {pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc;const loadingTask = pdfjsLib.getDocument(url);loadingTask.promise.then((pdf: any) => {state.show = true;pdfDoc = pdf;pdfPages.value = pdf.numPages;nextTick(() => {renderPage(1);});}).catch((err: any) => {console.error(err);pdfDoc = nullstate.show = false});} catch (error) {console.error(error)}
};
//渲染pdf文件
const renderPage = (num: number) => {pdfDoc?.getPage(num).then((page: any) => {const canvasId = "pdf-canvas-" + num;const canvas = <any>document.getElementById(canvasId);const ctx = canvas.getContext("2d");const dpr = window.devicePixelRatio || 1;const bsr =ctx.webkitBackingStorePixelRatio ||ctx.mozBackingStorePixelRatio ||ctx.msBackingStorePixelRatio ||ctx.oBackingStorePixelRatio ||ctx.backingStorePixelRatio ||1;const ratio = dpr / bsr;const viewport = page.getViewport({ scale: pdfScale.value });canvas.width = viewport.width * ratio;canvas.height = viewport.height * ratio;canvas.style.width = viewport.width + "px";canvas.style.height = viewport.height + "px";ctx.setTransform(ratio, 0, 0, ratio, 0, 0);const renderContext = {canvasContext: ctx,viewport: viewport,};page.render(renderContext);if (num < pdfPages.value) {renderPage(num + 1);}});
};
function openModal() {state.visible = true;nextTick(() => {loadFile(props.file.previewPath);})
}
function handleCancel() {state.visible = false;
}
async function exportBtn() {try {state.downLoading = trueif (!props.file?.path) {message.warning(`无地址,可供下载`)return;}await downloadBlobAsync(props.file?.path, props.file?.originalFileName, true)} catch (error: any) {message.error(error)} finally {state.downLoading = false}
}defineExpose({openModal
})
</script>
<style>
#videoContainer {height: 500px;width: 100%;overflow: auto;.canvas {width: 80% !important;margin: 0 auto;}
}.preview-btns-posi {position: absolute;top: 10px;right: 50px;
}
</style>
/**下载文件 */
export const downloadBlobAsync = (blob: Blob | string, fileName: string, isUrl = false) => {return new Promise<void>((resolve, reject) => {try {//对于<a>标签,只有 Firefox 和 Chrome(内核) 支持 download 属性//IE10以上支持blob但是依然不支持downloadif ('download' in document.createElement('a')) {//支持a标签download的浏览器const link = document.createElement('a'); //创建a标签link.download = fileName; //a标签添加属性link.style.display = 'none';link.href = isUrl ? blob as string : URL.createObjectURL(blob as Blob);document.body.appendChild(link);link.click(); //执行下载URL.revokeObjectURL(link.href); //释放urldocument.body.removeChild(link); //释放标签} else {//其他浏览器(navigator as any)?.msSaveBlob(blob, fileName);}} catch (error) {console.log(error)reject(error);} finally {setTimeout(() => {resolve()}, 500)}})
};