使用pdf.js实现PDF缩放时出现Invalid page request错误求助
问题描述
我用pdf.js实现PDF放大缩小功能,以下是渲染/重渲染PDF的函数:
const renderPdfPage = async (pdf: any, pdfJS: any, pageNum: number) => { if (!canvasRef || !canvasRef.current) return; const docCavas = document.getElementById("the-canvas" + pageNum); if (!docCavas) { const el = window.document.createElement("canvas") as HTMLCanvasElement; el.id = "the-canvas" + pageNum; canvasRef.current.append(el); } if(pageNum > pdf.numPages){ return; } const page = await pdf.getPage(pageNum); const viewport = page.getViewport({ scale: pdfScale }); let canvas = document.getElementById('the-canvas' + pageNum) as HTMLCanvasElement; const canvasContext = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; const renderContext = { canvasContext, viewport }; const renderTask = page.render(renderContext); renderTask.promise.then(function () { const textContent = page.getTextContent(); return textContent; }).then(function (textContent: string) { const textLayer = document.querySelector(`.${styles.textLayer}`) as HTMLDivElement; if (!textLayer) return; textLayer.style.left = canvas.offsetLeft + 'px'; textLayer.style.top = canvas.offsetTop + 'px'; textLayer.style.height = canvas.offsetHeight + 'px'; textLayer.style.width = canvas.offsetWidth + 'px'; textLayer.style.setProperty('--scale-factor', pdfScale.toString()); pdfJS.renderTextLayer({ textContentSource: textContent, container: textLayer, viewport: viewport, textDivs: [] }); }); }
现在遇到问题:有时候获取PDF页面失败,抛出错误:
api.js:2917 Uncaught (in promise) Error: Invalid page request. at WorkerTransport.getPage (api.js:2917:29) at PDFDocumentProxy.getPage (api.js:837:28) at renderPdfPage (Previewer.tsx:55:32) at getPage (Previewer.tsx:136:68)
错误来自const page = await pdf.getPage(pageNum);这行代码,检查后没找到原因。以下是缩放功能函数:
const handleZoomOut = async (pdfUrl: any) => { if (!pdfUrl) { return; } var zoomoutbutton = document.getElementById("zoomoutbutton") as HTMLButtonElement; zoomoutbutton.onclick = function () { if (pdfScale <= 0.25) { return; } setPdfScale(pdfScale - 0.25); displayPage(currentPdf, pageNum); } }
请问遗漏了什么?该怎么修复?
问题分析与修复方案
1. 补全页码边界判断
当前只判断了pageNum > pdf.numPages,但pdf.js的页码是从1开始的,若pageNum为0或负数,调用getPage必然抛出Invalid page request错误。修改判断逻辑:
if(pageNum < 1 || pageNum > pdf.numPages){ return; }
2. 校验PDF实例有效性
传入renderPdfPage的pdf(也就是currentPdf)可能已经被销毁或失效(比如PDF加载中断、组件重渲染后引用丢失),此时调用getPage也会报错。在函数开头加校验:
if (!pdf || pdf.destroyed) { return; }
3. 修复缩放函数的状态同步问题
handleZoomOut里的pageNum可能是过时的状态值,比如组件重渲染后未同步更新,导致传入无效页码。建议:
- 用React状态管理
pageNum,确保点击缩放按钮时获取最新值; - 调用
displayPage时,传入当前实际显示的页码,而非依赖外部变量。
4. 处理异步渲染的竞态问题
快速多次点击缩放按钮会触发多次渲染请求,前一个请求未完成时,后一个请求的状态已变化,可能导致页码请求失效。可以给渲染任务加取消逻辑:
// 定义变量保存当前渲染任务 let currentRenderTask = null; const renderPdfPage = async (pdf: any, pdfJS: any, pageNum: number) => { // 取消之前未完成的渲染任务 if (currentRenderTask) { currentRenderTask.cancel(); } // ... 原有代码 const renderTask = page.render(renderContext); currentRenderTask = renderTask; renderTask.promise.then(function () { currentRenderTask = null; // ... 原有代码 }).catch(err => { // 忽略渲染取消的报错 if (err.name !== 'RenderingCancelledException') { console.error(err); } currentRenderTask = null; }); }
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

