需求:
客户在浙政钉需要文件预览功能(包括PDF和Word)。原本都是使用浙政钉提供的API,但是新版本已经不在提供文件预览API了。组员和浙政钉工作人员沟通后对方表示需要我们自行实现。
问题:
一般预览PDF都会使用PDF.js这个库,在本地实现完成后,上传到浙政钉,ios没什么问题,一看安卓,好家伙,直接报错了。后来排除发现基本上机型自带的浏览器都可以预览,但是浙政钉里内置的浏览器版本太低了…所以在这里卡了很久
换了好多的组件库,但是基本上的组件都是基于pdfjs来实现文件预览。
项目相关:vue3 + vite 2.9.9
解决:
下载 pdfjs-dist ,注意下载依赖时要下载 ^2.5.207 这个版本,这个版本提供ES5的依赖,下面是实现的代码demo
onMounted(async () => {
pdfjs = await import('pdfjs-dist/es5/build/pdf')
pdfjsWorker = await import('pdfjs-dist/es5/build/pdf.worker.entry')
// 注意这里引入时 需要引入es5中的js 来兼容低版本的安卓浏览器
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker
await resolvePdf()
})
const resolvePdf = () => {
var getPreviewUrl =
Tool.apiurl() + '/api/dev/download/getPreview?resource=' + encodeURI('web/fileatt/' + filepath)
axios({
url: getPreviewUrl,
method: 'post',
responseType: 'blob'
}).then((res) => {
// 根据接口返回文件流来实现预览
let blob = new Blob([res.data], { type: 'application/pdf' }) // 设置类型
blobToArrayBuffer(blob).then((arrayBuffer) => {
const loadingTask = pdfjs.getDocument(arrayBuffer)
loadingTask.promise.then((pdf) => {
state.pdfCtx = pdf
state.pageNum = pdf.numPages
nextTick(() => {
renderPdf(1, 1)
})
})
})
})
}
const renderPdf = (num, scale) => {
state.pdfCtx.getPage(num).then((page) => {
// const canvas: any = document.getElementById(`pdf-canvas-${num}`);
const canvas = document.getElementById('pdf-canvas')
const ctx = canvas.getContext('2d')
// test
let dpr = window.devicePixelRatio || 1
let bsr =
ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio ||
1
let ratio = dpr / bsr
let scalNum = scale || 1
let viewport = page.getViewport({
scale: screen.availWidth / page.getViewport({ scale: 1 }).width
})
canvas.width = viewport.width * ratio * scalNum
canvas.height = viewport.height * ratio * scalNum
state.width = viewport.width * ratio * scalNum
state.height = viewport.height * ratio * scalNum
canvas.style.width = viewport.width * scalNum + 'px'
canvas.style.height = viewport.height * scalNum + 'px'
let renderContext = {
//这里transform比较关键 保证根据手势缩放后的清晰度和等比例
transform: [ratio * scalNum, 0, 0, ratio * scalNum, 0, 0],
canvasContext: ctx,
viewport: viewport
}
})
}
原作者在实现上写的更详细,但是本文主要是在原文章基础上再加了pdfjs 低版本的更新
参考代码:
https://blog.csdn.net/qq_44848480/article/details/135583649