Next.js14使用pdfjsLib读取PDF遇元素类型无效错误求助
问题
我用Next.js 14开发PDF文件合并功能,需要基于内容合并两个PDF。但执行const pdf = await pdfjsLib.getDocument(content).promise;读取PDF内容时,出现如下错误:
Unhandled Runtime Error Error: Element type is invalid. Received a promise that resolves to: [object Promise]. Lazy element type must resolve to a class or function.
我没用到懒加载元素,试过添加/移除useEffect、调整async/await,错误还是存在。相关代码如下:
page.tsx
import PDFFileMerger from "@/components/PDFFileMerger"; import Image from "next/image"; import React, { useState } from 'react'; export default function Home() { return ( <main className="overflow-hidden"> <PDFFileMerger /> </main> ); }
PDFFileMerger.tsx
"use client"; import React, { useState, ChangeEvent, useEffect } from 'react'; import { PDFDocument, rgb } from 'pdf-lib'; import * as pdfjsLib from 'pdfjs-dist'; function PDFFileMerger() { const [file1, setFile1] = useState<File | null>(null); const [file2, setFile2] = useState<File | null>(null); const [mergedPdf, setMergedPdf] = useState<Uint8Array | null>(null); const [textOutput, setTextOutput] = useState<string>(''); useEffect(() => { if (!file1) return; const fileReader = new FileReader(); fileReader.onload = async function() { const content = this.result; if (content) { try { const pdf = await pdfjsLib.getDocument(content).promise; console.log(pdf); } catch (error) { console.error('Error loading PDF:', error); } } }; fileReader.readAsArrayBuffer(file1); }, [file1] ); const handleFile1Change = (event: React.ChangeEvent<HTMLInputElement>) => { const selectedFile = event.target.files?.[0]; setFile1(selectedFile || null); }; return ( <div> <input id="pdf1" type="file" accept=".pdf" onChange={handleFile1Change} /> <input type="file" accept=".pdf" onChange={handleFile2Change} /> <button onClick={handleMerge}>Merge PDFs</button> {mergedPdf && ( <a href={URL.createObjectURL(new Blob([mergedPdf], { type: 'application/pdf' }))} target="_blank" rel="noopener noreferrer" download="merged.pdf" > Open Merged PDF </a> )} <div id="textOutput">{textOutput}</div> </div> ); }; export default PDFFileMerger;
解决方案
这个错误的根源是pdfjs-dist在Next.js客户端组件中的导入和初始化问题,和你的async/await、useEffect写法无关。按以下步骤修复:
正确导入pdfjs-dist的构建版本
在客户端组件中,不能直接导入pdfjs-dist,需要导入浏览器环境专用的编译版本,并指定worker路径:import * as pdfjsLib from 'pdfjs-dist/build/pdf'; import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry'; pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;简化PDF读取逻辑
用file.arrayBuffer()替代FileReader,避免回调嵌套,代码更简洁:useEffect(() => { if (!file1) return; const loadPDF = async () => { try { const content = await file1.arrayBuffer(); const pdf = await pdfjsLib.getDocument(content).promise; console.log('PDF loaded:', pdf); } catch (error) { console.error('Error loading PDF:', error); } }; loadPDF(); }, [file1]);补全缺失函数
代码中handleFile2Change和handleMerge未定义,会导致运行时错误,补充实现:const handleFile2Change = (event: React.ChangeEvent<HTMLInputElement>) => { const selectedFile = event.target.files?.[0]; setFile2(selectedFile || null); }; const handleMerge = async () => { if (!file1 || !file2) return; try { const pdfDoc = await PDFDocument.create(); // 合并第一个PDF页面 const pdf1Bytes = await file1.arrayBuffer(); const pdf1Doc = await PDFDocument.load(pdf1Bytes); const pdf1Pages = await pdfDoc.copyPages(pdf1Doc, pdf1Doc.getPageIndices()); pdf1Pages.forEach(page => pdfDoc.addPage(page)); // 合并第二个PDF页面 const pdf2Bytes = await file2.arrayBuffer(); const pdf2Doc = await PDFDocument.load(pdf2Bytes); const pdf2Pages = await pdfDoc.copyPages(pdf2Doc, pdf2Doc.getPageIndices()); pdf2Pages.forEach(page => pdfDoc.addPage(page)); // 生成合并后的PDF数据 const mergedBytes = await pdfDoc.save(); setMergedPdf(mergedBytes); } catch (error) { console.error('Error merging PDFs:', error); } };安装必要依赖
确保已安装所有依赖包:npm install pdf-lib pdfjs-dist
内容的提问来源于stack exchange,提问作者tonystark20
相关产品推荐
相关产品推荐

