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

如何在Node.js(Express)中识别PDF为文本/图像/混合类型?

解决方案:PDF类型检测与针对性文本提取

核心思路

先通过pdf-parse提取文本,根据提取到的有效文本量判断PDF类型:

  • 若有效文本量达到阈值,判定为文本型PDF,直接使用普通提取结果
  • 若有效文本量极低,判定为图像型/混合型PDF,调用Tesseract OCR进行识别处理

步骤1:安装依赖

需要额外安装OCR和PDF页面渲染相关工具:

npm install tesseract.js pdfjs-dist canvas

步骤2:修改上传接口代码

更新/upload路由,加入类型检测和OCR处理逻辑:

const express = require('express');
const app = express();
const upload = require('multer')({ dest: './uploads' });
const fs = require('fs');
const path = require('path');
const pdfParse = require('pdf-parse');
const { createWorker } = require('tesseract.js');
const pdfjsLib = require('pdfjs-dist');
const pdfjsWorker = require('pdfjs-dist/build/pdf.worker.entry');
const { createCanvas } = require('canvas');

pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;

app.post("/upload", upload.single("file"), async (req, res) => {
  console.log(req.file);
  let extractedText = '';
  const minTextLength = 10; // 可根据业务调整的文本阈值

  try {
    const dataBuffer = fs.readFileSync(req.file.path);
    // 第一步:尝试普通文本提取
    const pdfData = await pdfParse(dataBuffer);
    // 清理文本:去掉所有空白字符,仅保留有效内容
    const cleanedText = pdfData.text.trim().replace(/\s+/g, '');

    if (cleanedText.length >= minTextLength) {
      // 文本型PDF:直接使用提取结果
      extractedText = pdfData.text;
    } else {
      // 图像/混合型PDF:启动Tesseract OCR处理
      const worker = await createWorker('eng'); // 切换语言可替换为'chi_sim'等
      const pdf = await pdfjsLib.getDocument({ data: dataBuffer }).promise;
      const numPages = pdf.numPages;

      // 逐页渲染为图片并识别
      for (let pageNum = 1; pageNum <= numPages; pageNum++) {
        const page = await pdf.getPage(pageNum);
        const viewport = page.getViewport({ scale: 2.0 }); // 放大页面提升识别精度
        const canvas = createCanvas(viewport.width, viewport.height);
        const context = canvas.getContext('2d');

        await page.render({ canvasContext: context, viewport: viewport }).promise;
        const imageBuffer = canvas.toBuffer('image/png');

        const { data: { text } } = await worker.recognize(imageBuffer);
        extractedText += `${text}\n\n`;
      }

      await worker.terminate();
    }

    // 保存提取的文本文件
    const txtFilePath = path.join('./uploads', `${req.file.originalname}.txt`);
    await fs.promises.writeFile(txtFilePath, extractedText);
    
    console.log("文本提取并保存成功");
    res.send(`文件上传完成,文本已提取并保存为 ${req.file.originalname}.txt`);
  } catch (error) {
    console.error(error);
    res.status(500).send("PDF文本提取或文件保存过程中发生错误");
  }
});

// 原有的/search路由保持不变
app.get("/search", async (req, res) => {
  const keyword = req.query.keyword.toLowerCase();
  const directoryPath = path.join(__dirname, "uploads");
  let filesContainingKeyword = [];

  try {
    const files = await fs.promises.readdir(directoryPath);

    for (let file of files) {
      if (file.endsWith(".txt")) {
        let filePath = path.join(directoryPath, file);
        let data = await fs.promises.readFile(filePath, "utf8");
        let lowerCaseData = data.toLowerCase();
        if (lowerCaseData.includes(keyword)) {
          let index = lowerCaseData.indexOf(keyword);
          let preview = data.substring(index, index + 100) + "...";
          let pdfFile = file.replace(".txt", "");
          filesContainingKeyword.push({ filename: pdfFile, preview: preview });
          console.log(`在${filePath}中找到关键词`);
        } else {
          console.log(`在${filePath}中未找到关键词`);
        }
      }
    }

    res.send(filesContainingKeyword);
  } catch (err) {
    console.error("无法扫描目录: " + err);
    res.status(500).send("服务器内部错误");
  }
});

app.listen(3000, () => console.log("服务启动在3000端口"));

关键说明

  1. 阈值调整:minTextLength可根据业务场景调整,比如如果存在仅含少量文本的合法文本PDF,可适当降低阈值;若图像PDF容易产生噪声文本,可提高阈值。
  2. 性能优化:Tesseract OCR资源消耗较高,建议:
    • 对大文件使用异步队列处理,避免阻塞主线程
    • 缓存已处理的PDF结果,重复上传时直接复用
  3. 混合类型PDF:当前实现会对所有页面进行OCR,若需更精细化处理(仅对图像页面OCR),可通过pdfjs的页面内容分析判断是否包含文本元素,但会增加逻辑复杂度。

内容的提问来源于stack exchange,提问作者Anandhu Remanan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 10:38:25