> 技术文档 > 【vue3+vue-pdf-embed】实现PDF+图片预览

【vue3+vue-pdf-embed】实现PDF+图片预览


【vue3+vue-pdf-embed】实现PDF+图片预览

    • 项目背景
    • 项目代码
    • 分析代码

项目背景

技术栈:vue3+Ts+elementplus
需要实现PDF和图片预览
图片预览很好解决了,可以用elementplus 自带的组件el-image 可实现
PDF预览可以用搜了一圈,有两个方案,一个是vue-office-pdf,另一个是vue-pdf-embed
由于项目需求,只需要做预览,且只支持 PDF,也不需要什么高级文档操作功能,所以我就采用了vue-pdf-embed

项目代码

html 代码

<my-dialog ref=\"myDialogRef\" width=\"60%\" max-height=\"70vh\"> <div v-loading=\"dialogLoading\" class=\"reviewDiv\"> <el-image v-if=\"imageDialogVisible\" :src=\"imageSrc\" style=\"max-width: 100%;\" fit=\"contain\" /> <vue-pdf-embed v-else ref=\"pdfRef\" :source=\"imageSrc\" :page=\"pdfPage\" @password-requested=\"handlePasswordRequest\" @rendered=\"handleDocumentRender\" /> <div v-show=\"!imageDialogVisible && pageCount\" class=\"text-center\"> <el-button :disabled=\"pdfPage <= 1\" @click=\"pdfPage--\"></el-button> <span class=\"mx-4\">{{ pdfPage }} / {{ pageCount }}</span> <el-button :disabled=\"pdfPage >= pageCount\" @click=\"pdfPage++\"></el-button> </div> </div></my-dialog>

js 代码

const imageSrc = ref(\'\')const myDialogRef = ref()const imageDialogVisible = ref<boolean>(false)const dialogLoading = ref<boolean>(false)const openFileDialog = (file: any) => { dialogLoading.value = true // 释放之前创建的对象URL if (imageSrc.value) { URL?.revokeObjectURL(imageSrc.value) } // 创建新的对象URL if (file.raw) { // 本地预览 imageSrc.value = URL?.createObjectURL(file.raw) dialogLoading.value = false } else { // 编辑远程预览 const targetFile = getTargetFile.value(file) apiDownloadFile(targetFile[0].fileDocumentId).then((response: any) => { imageSrc.value = response.request.responseURL setTimeout(() => { dialogLoading.value = false }, 1000) }) } const isImage = judgeIcon(file) === \'image\' myDialogRef.value?.openDialog(isImage ? \'图片预览\' : \'PDF预览\') if (isImage) { imageDialogVisible.value = true } else { imageDialogVisible.value = false }}const pdfPage = ref<number>(1)const pageCount = ref<number>(0)const pdfRef = ref()function handleDocumentRender () { pageCount.value = pdfRef.value?.doc?.numPages // 这里是重点}function handlePasswordRequest (callback: any, retry: boolean) { callback(prompt(retry ? \'Enter password again\' : \'Enter password\'))}

分析代码

首先预览有本地预览和远程预览

  1. 本地预览顾名思义:就是在本地上传还没有调接口的PDF或图片进行预览,这时候通过URL 接口里面的静态方法并往里面传file.raw 便可得到 本地PDF/图片链接了
    具体请看这里URL:createObjectURL() 静态方法
  2. 远程预览:即从后端接口返回回来的PDF/图片 进行预览,这时候需要先调用下载接口 ,接口会返回 对应的链接
    通过以上两步:可以把 需要传递的 source 的值搞定

需要PDF很大,有很多页,这时候预览需要分页,但是分页的时候有一个问题,就是一直找不到对应的总页码即pageCount ,有看很多文章,要么通过rendered方法传参,但文档根据不支持传参,【vue3+vue-pdf-embed】实现PDF+图片预览
vue-pdf-embed
后面自己试了一下,居然 使用 ref 的方式 pdfRef.value?.doc?.numPages ,拿到了总页码,至此,后面就很容易解决了