You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 01:05:06