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均出现上述错误和重复回调
原因分析
重复触发
onSourceSuccess:- 若
pdfFile是包含额外字段(如DrawingId)的对象,每次组件渲染时,模板字符串会强制将对象转为[object Object],后续pdfFile更新或组件重渲染会导致fileprop频繁变化,触发多次源加载。 - 未对
file值做缓存,React重渲染时会重复创建新的file引用,触发Document组件的重新加载流程。
- 若
"Worker was destroyed"错误:
- react-pdf依赖PDF.js的Worker线程解析PDF,当
fileprop频繁变化时,旧的Worker线程会被销毁,但旧的加载任务仍在执行,导致抛出该错误。 - 使用
entry.webpack入口可能存在Worker打包或加载的兼容性问题,尤其在Webpack 5环境下。 - 部分PDF无内容可能是Base64数据格式错误(如包含多余字符、前缀错误),导致Worker解析失败。
- react-pdf依赖PDF.js的Worker线程解析PDF,当
解决方法
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
相关产品推荐
相关产品推荐

