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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 07:30:10