Next.js中用pdfjs-dist转PDF为图片遇ModuleParseError求助
问题描述
在Next.js客户端组件中尝试将用户上传的PDF文件转换为图片,使用pdfjs-dist库实现后,运行时出现以下错误:
Uncaught ModuleParseError: Module parse failed: Unexpected character '�' (1:2)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.
(Source code omitted for this binary file)
实现代码如下:
"use client" import { useState, useEffect } from 'react'; import { useRouter } from 'next/navigation'; const PDFJS = require("pdfjs-dist/webpack"); const Dashboard = () => { const router = useRouter(); const [selectedFile, setSelectedFile] = useState(null); const [uploadSuccess, setUploadSuccess] = useState(false); const handleLogout = () => { localStorage.removeItem('authToken'); router.push('/login'); }; const handleRemoveFile = () => { setSelectedFile(null); }; const handleFileUpload = (e) => { const fileInput = e.target; const file = fileInput.files[0]; if (file) { setSelectedFile(file, file.name); console.log('PDF attached:', file.name); } }; const convertPdfToImages = async (file) => { const images = []; const data = await readFileData(file); const pdf = await PDFJS.getDocument(data).promise; const canvas = document.createElement("canvas"); for (let i = 0; i < pdf.numPages; i++) { const page = await pdf.getPage(i + 1); const viewport = page.getViewport({ scale: 1 }); const context = canvas.getContext("2d"); canvas.height = viewport.height; canvas.width = viewport.width; await page.render({ canvasContext: context, viewport: viewport }).promise; images.push(canvas.toDataURL()); } canvas.remove(); return images; }; const handleUpload = async () => { try { const images = await convertPdfToImages(selectedFile); console.log("Images:", images); setUploadSuccess(true); } catch (error) { console.error("Error converting PDF to images:", error); } }; useEffect(() => { const authToken = localStorage.getItem('authToken'); if (!authToken) { router.push('/login'); } }, []); return ( <div className="min-h-screen bg-gray-100"> <nav className="bg-indigo-600 p-4 flex justify-between items-center"> <h1 className="text-2xl text-white font-semibold">TaxGPT</h1> <button onClick={handleLogout} className="bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded" > Log Out </button> </nav> <div className="max-w-md w-full space-y-8 mx-auto mt-8 p-4"> <div> <h2 className="text-3xl font-extrabold text-gray-900">Welcome to Dashboard</h2> </div> <div className="bg-white p-4 rounded shadow"> <label className="block text-gray-700 text-sm font-bold"> Attach your document in PDF: </label> <div className="relative mt-2"> <label className="cursor-pointer bg-indigo-600 text-white py-2 px-4 rounded text-sm font-medium"> Choose a File <input type="file" accept=".pdf" className="sr-only" onChange={handleFileUpload} /> </label> {selectedFile && ( <div className="mt-2 flex justify-between items-center"> <span className="text-gray-700 text-sm">{selectedFile.name}</span> <button onClick={handleRemoveFile} className="text-red-600 hover:text-red-700" > X </button> </div> )} </div> </div> {selectedFile && !uploadSuccess && ( <button onClick={handleUpload} className="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded text-sm font-medium" > Upload </button> )} </div> </div> ); }; export default Dashboard;
解决方案
这个错误源于pdfjs-dist/webpack引入了二进制文件,Next.js默认webpack配置未适配这类文件处理,按以下步骤修复:
1. 替换pdfjs导入方式
放弃pdfjs-dist/webpack,改用浏览器兼容版本并配置worker:
// 替换原require语句 import * as pdfjsLib from 'pdfjs-dist'; import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry'; // 在组件内初始化worker pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;
2. 补充缺失的readFileData函数
代码中调用了未定义的readFileData,添加该函数:
const readFileData = (file) => { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = (e) => resolve(e.target.result); reader.onerror = reject; reader.readAsArrayBuffer(file); }); };
3. 修正setSelectedFile的错误用法
原代码中setSelectedFile(file, file.name)不符合useState setter的语法,文件对象本身包含name属性,直接传入即可:
setSelectedFile(file);
4. 可选:配置webpack处理二进制文件
若仍报错,在项目根目录创建next.config.js,添加webpack规则:
/** @type {import('next').NextConfig} */ const nextConfig = { webpack: (config) => { config.module.rules.push({ test: /\.pdf$/, use: [ { loader: 'url-loader', options: { limit: 8192, name: '[name].[hash:8].[ext]', }, }, ], }); return config; }, }; module.exports = nextConfig;
执行以下命令安装依赖:
npm install url-loader --save-dev
内容的提问来源于stack exchange,提问作者Hello World
相关产品推荐
相关产品推荐

