Pdfjs-dist在Next.js14 App Router(JS)中提取PDF文本报错的解决方法
问题修复方案
核心错误原因
你遇到的「Element type is invalid」错误,根源在于使用异步函数作为filter的回调:
filter需要同步返回布尔值,但异步函数会返回Promise,导致pdf_files变成一个Promise数组而非文本内容数组。如果后续尝试在JSX中渲染这个数组,React会因收到Promise而非有效元素/文本而抛出错误。
此外代码中还有几处关键问题:
- Worker配置错误:
pdfjs.GlobalWorkerOptions.workerSrc需要的是Worker脚本的URL,而非导入的模块对象 - 冗余的
await:doc已经是await后的结果,无需再次await doc - 变量名错误:
pdf.getPage(i)应为doc.getPage(i) - 低效的Blob URL创建:pdfjs支持直接传入ArrayBuffer,无需转成Blob URL
修正后的完整代码(Next.js 14 客户端组件)
'use client'; import * as pdfjs from "pdfjs-dist/build/pdf.mjs"; // 用?url后缀让Next.js返回Worker脚本的URL字符串 import workerUrl from "pdfjs-dist/build/pdf.worker.mjs?url"; // 初始化pdfjs Worker pdfjs.GlobalWorkerOptions.workerSrc = workerUrl; export default function PDFTextExtractor() { const handleFileSelect = async (e) => { const files = Array.from(e.target.files); // 单独封装PDF文本提取逻辑 const extractTextFromPDF = async (file) => { if (file.type !== "application/pdf") return null; const arrayBuffer = await file.arrayBuffer(); // 直接传入ArrayBuffer给pdfjs,无需Blob URL const doc = await pdfjs.getDocument({ data: arrayBuffer }).promise; let allText = ""; const numPages = doc.numPages; for (let i = 1; i <= numPages; i++) { const page = await doc.getPage(i); const content = await page.getTextContent(); // 给文本项之间添加空格,提升可读性 const pageText = content.items.map(item => item.str).join(" "); allText += pageText + "\n\n"; // 页面间添加换行分隔 } return { filename: file.name, text: allText }; }; // 用Promise.all批量处理所有文件,过滤掉非PDF的结果 const results = await Promise.all(files.map(extractTextFromPDF)); const pdfTexts = results.filter(result => result !== null); // 这里可以处理提取后的文本,比如存入状态用于渲染 console.log("提取的PDF文本:", pdfTexts); // setExtractedTexts(pdfTexts); // 若需渲染,可设置状态 }; return ( <div> <input type="file" multiple accept="application/pdf" onChange={handleFileSelect} /> {/* 可在此处渲染提取后的文本,例如: {pdfTexts.map((item, idx) => ( <div key={idx}> <h3>{item.filename}</h3> <pre>{item.text}</pre> </div> ))} */} </div> ); }
关键修正点说明
- Worker配置:通过
pdf.worker.mjs?url导入Worker脚本的URL,符合pdfjs对workerSrc的要求 - 异步处理逻辑:用
map + Promise.all替代filter,正确批量处理异步文件提取 - 代码精简:直接传入ArrayBuffer给
getDocument,省去Blob和URL创建步骤 - 变量修正:修复
pdf.getPage的变量名错误,移除冗余的await
内容的提问来源于stack exchange,提问作者Coder
相关产品推荐
相关产品推荐

