pdfjs渲染PDF至Canvas时中文不显示及cMap配置报错问题
解决pdfjs-dist v3.9.179 Canvas渲染中文不显示的问题
核心问题分析
你遇到的object is not extensible错误,是因为v3.x版本的pdfjs-dist模块对象已被冻结,无法直接添加cMapUrl属性。正确的cMap配置方式是在初始化PDF文档时传入配置参数,而非修改模块对象。另外原代码中textContent的类型处理也存在问题,会导致文本层渲染异常。
修复后的完整代码
const initPdf = async (pdfUrl: string) => { setPdfUrl(pdfUrl); const pdfJS = await import('pdfjs-dist/build/pdf'); pdfJS.GlobalWorkerOptions.workerSrc = window.location.origin + '/pdf.worker.min.js'; // 关键:将cMap配置传入getDocument,而非直接修改pdfJS对象 const pdf = await pdfJS.getDocument({ url: pdfUrl, cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@3.9.179/cmaps/', cMapPacked: true // 启用预打包的cMap,提升加载效率 }).promise; const page = await pdf.getPage(1); const viewport = page.getViewport({ scale: 1.5 }); const canvas: any = canvasRef.current; if (!canvas) return; 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(async function () { // 修正:getTextContent返回Promise,需要await获取结果 const textContent = await page.getTextContent(); return textContent; }).then(function (textContent) { const textLayer = document.querySelector(".textLayer") as HTMLDivElement; textLayer.style.left = canvas.offsetLeft + 'px'; textLayer.style.top = canvas.offsetTop + 'px'; textLayer.style.height = canvas.offsetHeight + 'px'; textLayer.style.width = canvas.offsetWidth + 'px'; pdfJS.renderTextLayer({ textContent: textContent, container: textLayer, viewport: viewport, textDivs: [] }); }); }
关键修复点说明
- cMap配置方式修改:在
getDocument中传入包含url、cMapUrl、cMapPacked的配置对象,避免直接修改不可扩展的模块对象。cMapPacked设为true对应CDN中预打包的cMap文件格式。 - 修正textContent获取逻辑:
page.getTextContent()返回的是Promise,必须用await获取实际的文本内容对象,否则会传递Promise给渲染函数导致文本层失效。 - 确保worker版本匹配:你的
pdf.worker.min.js必须和pdfjs-dist的版本(3.9.179)完全一致,否则可能出现兼容性问题。
额外注意事项
- 如果使用本地cMap资源,将
cMapUrl改为本地路径(如'/cmaps/'),并确保该目录下包含pdfjs-dist对应版本的cMap文件。 - 检查PDF文件是否嵌入了中文字体:如果PDF未嵌入字体,即使配置cMap也可能无法正常渲染,这种情况需要确保PDF生成时嵌入了必要的中文字体。
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

