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

React-PDF v6.2.0加载Base64 PDF报Worker was destroyed错误求助

React-PDF v6.2.0加载Base64 PDF出现"Worker was destroyed"错误及重复回调问题

问题场景

使用react-pdf v6.2.0开发自定义PDF查看器,加载API返回的Base64格式PDF,代码如下:

import React, { useState } from "react";
import { Document, Page } from "react-pdf/dist/esm/entry.webpack";

export function PDFViewer({ pdfFile }) {
  const [numPages, setNumPages] = useState(null);
  const [pageNumber, setPageNumber] = useState(1);

  return (
    <>
      <Document
        file={`data:application/pdf;base64,${pdfFile}`}
        onLoadSuccess={({ numPages }) => {
          console.log(`PDF File drawingId: ${pdfFile.DrawingId}`);
          setNumPages(numPages);
          setPageNumber(1);
          alert("PDF document loaded successfully!");
        }}
        onLoadProgress={({ loaded, total }) =>
          alert("Loading a document: " + (loaded / total) * 100 + "%")
        }
        onLoadError={(error) =>
          alert("Error while loading document! " + error.message)
        }
        onSourceSuccess={() => alert("Document source retrieved!")}
        onSourceError={(error) =>
          alert("Error while retrieving document source! " + error.message)
        }
      >
        <Page pageNumber={pageNumber || 1} />
      </Document>
    </>
  );
}

运行异常现象

  • 两次弹出Document source retrieved!
  • 弹出Error while loading document! Worker was destroyed
  • 弹出Loading a document: 100%和PDF document loaded successfully
  • 部分PDF无内容显示,所有PDF均出现上述错误和重复回调

原因分析

  1. 重复触发onSourceSuccess:

    • 若pdfFile是包含额外字段(如DrawingId)的对象,每次组件渲染时,模板字符串会强制将对象转为[object Object],后续pdfFile更新或组件重渲染会导致file prop频繁变化,触发多次源加载。
    • 未对file值做缓存,React重渲染时会重复创建新的file引用,触发Document组件的重新加载流程。
  2. "Worker was destroyed"错误:

    • react-pdf依赖PDF.js的Worker线程解析PDF,当file prop频繁变化时,旧的Worker线程会被销毁,但旧的加载任务仍在执行,导致抛出该错误。
    • 使用entry.webpack入口可能存在Worker打包或加载的兼容性问题,尤其在Webpack 5环境下。
    • 部分PDF无内容可能是Base64数据格式错误(如包含多余字符、前缀错误),导致Worker解析失败。

解决方法

1. 稳定file prop,避免重复加载

使用useMemo缓存生成的Data URL,仅当Base64数据变化时才更新,避免不必要的重渲染:

import React, { useState, useMemo } from "react";
import { Document, Page } from "react-pdf/dist/esm/entry.webpack";

export function PDFViewer({ pdfFile }) {
  const [numPages, setNumPages] = useState(null);
  const [pageNumber, setPageNumber] = useState(1);

  // 缓存Data URL,仅当pdfFile的Base64内容变化时更新
  const pdfFileUrl = useMemo(() => {
    // 提取纯Base64数据:若pdfFile是对象,取对应字段;若为字符串则直接使用
    const base64Content = typeof pdfFile === "string" ? pdfFile : pdfFile.base64Data;
    return `data:application/pdf;base64,${base64Content}`;
  }, [pdfFile]);

  return (
    <>
      <Document
        file={pdfFileUrl}
        onLoadSuccess={({ numPages }) => {
          console.log(`PDF File drawingId: ${pdfFile.DrawingId}`);
          setNumPages(numPages);
          // 初始pageNumber已为1,无需重复设置
          console.log("PDF document loaded successfully!");
        }}
        onLoadProgress={({ loaded, total }) =>
          console.log(`Loading a document: ${((loaded / total) * 100).toFixed(2)}%`)
        }
        onLoadError={(error) =>
          console.error("Error while loading document: ", error.message)
        }
        onSourceSuccess={() => console.log("Document source retrieved!")}
        onSourceError={(error) =>
          console.error("Error retrieving document source: ", error.message)
        }
      >
        <Page pageNumber={pageNumber || 1} />
      </Document>
    </>
  );
}

2. 修正Worker配置

若使用Webpack 5,改用适配的入口,并可手动指定CDN Worker避免本地加载异常:

// 替换导入入口
import { Document, Page, pdfjs } from "react-pdf/dist/esm/entry.webpack5";

// 配置CDN Worker
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.js`;

3. 验证Base64数据有效性

  • 提取pdfFile中的Base64字符串,保存为本地.pdf文件,确认能正常打开,排除数据损坏问题。
  • 确保Base64字符串不含data:application/pdf;base64,前缀,避免重复拼接。

4. 替换弹窗为控制台输出

频繁使用alert会阻塞JS执行,干扰加载流程,改用console.log/error调试。


内容的提问来源于stack exchange,提问作者usagibear

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 00:10:43