【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// 释放之前创建的对象URLif (imageSrc.value) {URL?.revokeObjectURL(imageSrc.value)}// 创建新的对象URLif (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.responseURLsetTimeout(() => {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'))
}
分析代码
首先预览有本地预览和远程预览
- 本地预览顾名思义:就是在本地上传还没有调接口的PDF或图片进行预览,这时候通过URL 接口里面的静态方法并往里面传file.raw 便可得到 本地PDF/图片链接了
具体请看这里URL:createObjectURL() 静态方法 - 远程预览:即从后端接口返回回来的PDF/图片 进行预览,这时候需要先调用下载接口 ,接口会返回 对应的链接
通过以上两步:可以把 需要传递的 source 的值搞定
需要PDF很大,有很多页,这时候预览需要分页,但是分页的时候有一个问题,就是一直找不到对应的总页码即pageCount ,有看很多文章,要么通过rendered方法传参,但文档根据不支持传参,
vue-pdf-embed
后面自己试了一下,居然 使用 ref 的方式 pdfRef.value?.doc?.numPages ,拿到了总页码,至此,后面就很容易解决了