javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > JavaScript提取Word文本

JavaScript实现纯前端提取Word文本的完整教程

作者:Eiceblue

在日常前端开发中,Word 文档的文本提取是一个高频需求,本文将结合 React 技术栈,为大家详细介绍如何使用 Spire.Doc for JavaScript 实现 Word 文档文本的提取与下载,希望对大家有所帮助

在日常前端开发中,Word 文档的文本提取是一个高频需求 —— 在线文档预览、内容检索、格式校验、数据入库等场景都依赖这一能力。传统方案往往需要将文件上传到后端服务器进行处理,不仅增加了带宽消耗和服务器负载,还带来了数据隐私方面的隐患。

Spire.Doc for JavaScript 提供了一种全新的解决思路 — 直接在浏览器端通过 WebAssembly 完成 Word 文档的读取与文本提取,无需任何后端服务支持。

本文将结合 React 技术栈,详细介绍如何使用 Spire.Doc for JavaScript 实现 Word 文档文本的提取与下载。

一、核心技术原理

1.1 WASM 运行机制

Spire.Doc for JavaScript 本质是将高性能原生文档处理内核编译为 WebAssembly,在浏览器沙箱中运行。整个加载流程分为三步:

1.2 虚拟文件系统(VFS)

WASM 运行在沙箱中,无法直接访问本地文件系统。Spire.Doc 通过 Emscripten 提供的 FS 接口模拟了一套虚拟文件系统:

1.3 文本提取核心 API

Document.GetText() 是提取纯文本的核心方法,它会遍历文档所有章节、段落、文本框,按顺序拼接所有可编辑文本内容,保留换行符以维持段落结构。

二、环境配置与项目初始化

2.1 安装依赖

首先,在 React 项目中安装并整合了多个组件的 Spire.Office:

npm i spire.office

该产品提供免费社区版(使用时注意限制)。

2.2 迁移核心运行时文件

安装完成后,需要将 node_modules 中 Spire.Doc for JavaScript 的运行时文件复制到 React 项目的 public 文件夹中:

为什么放在 public 目录?

因为 WASM 的加载需要通过 JavaScript 主线程以异步方式请求 .wasm 文件及相关资源。放在 public 目录下可以确保构建工具(如 Webpack)不会错误地处理或重命名这些文件,且能通过 process.env.PUBLIC_URL 准确访问。

2.3 准备字体资源

浏览器和 WASM 环境默认不包含系统字体。如果待处理的 Word 文档中使用了特殊字体(如 Calibri、Times New Roman 或中文字体),而 VFS 中缺失该字体,提取出的文本可能会出现乱码或文本错位。

建议将项目常用字体文件(如 Arial.ttf、CALIBRI.ttf、MSYH.TTC 等)一并放入 public/font/ 目录。

三、提取 Word 文本 - React 完整实现方案

下面以 React 函数组件为例,完整实现「文件上传 → 解析提取 → 导出下载」的全流程。

3.1 加载 WASM 模块

import React, { useState, useEffect } from 'react';

function App() {
  const [wasmModule, setWasmModule] = useState(null);
  const [selectedFile, setSelectedFile] = useState(null);
  const [isExtracting, setIsExtracting] = useState(false);
  const [error, setError] = useState(null);
  const [fontLoaded, setFontLoaded] = useState(false);

  // 加载 Spire.Doc WASM 模块
  useEffect(() => {
    (async () => {
      try {
        const publicUrl = process.env.PUBLIC_URL || '';
        const spireModule = await import(
          /* webpackIgnore: true */ `${publicUrl}/spire.doc.js`
        );
        const rawModule = spireModule.default || spireModule;
        window.wasmModule = typeof rawModule === 'function'
          ? await rawModule({
              locateFile: (p) =>
                p.endsWith('.wasm') ? `${publicUrl}/${p}` : p,
            })
          : rawModule;
        setWasmModule(window.wasmModule);
      } catch (err) {
        console.error('WASM 加载失败:', err);
        setError('无法加载文档处理引擎,请刷新页面重试。');
      }
    })();
  }, []);

这里的关键点是使用动态 import() 加载 spire.doc.js,并通过 locateFile 回调指定 WASM 文件的路径。/* webpackIgnore: true */ 注释确保 Webpack 不会尝试打包这个动态导入的模块。

3.2 文件选择与状态管理

  const handleFileChange = (event) => {
    const file = event.target.files[0];
    if (file) {
      setSelectedFile(file);
      setError(null);
    }
  };

文件选择逻辑简洁明了,用户选择文件后将其存入状态,同时清除之前的错误信息。

3.3 文本提取核心函数

这是整个组件的核心部分,完整实现了从文件读取到文本提取再到下载的全流程:

  const extractTextFromUploadedFile = async () => {
    if (!selectedFile) {
      setError('请先选择一个 Word 文档。');
      return;
    }

    const wasmDoc = window.wasmModule?.spiredoc;
    if (!wasmDoc) {
      setError('文档引擎尚未加载,请稍候。');
      return;
    }

    setIsExtracting(true);
    setError(null);

    try {
      // 3.3.1 预加载字体(仅加载一次)
      if (!fontLoaded) {
        await window.spire.FetchFileToVFS(
          'Arial.ttf',
          '/Library/Fonts/',
          `${process.env.PUBLIC_URL}/static/font/`
        );
        setFontLoaded(true);
      }

      // 3.3.2 将用户上传的文件读为 Uint8Array
      const arrayBuffer = await selectedFile.arrayBuffer();
      const uint8Array = new Uint8Array(arrayBuffer);
      const fileName = selectedFile.name;

      // 写入 VFS
      window.dotnetRuntime.Module.FS.writeFile(fileName, uint8Array);

      // 3.3.3 创建 Document 实例并加载文件
      const doc = new wasmDoc.Document();
      doc.LoadFromFile(fileName);

      // 3.3.4 提取全部文本
      const documentText = doc.GetText();

      // 3.3.5 释放资源
      doc.Dispose();

      // 3.3.6 下载文本文件
      const blob = new Blob([documentText], { type: 'text/plain;charset=utf-8' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `extracted_${selectedFile.name.replace(/\.[^.]+$/, '')}.txt`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);

      // 清理 VFS 中的临时文件
      window.dotnetRuntime.Module.FS.unlink(fileName);

      // 重置状态
      setSelectedFile(null);
      document.getElementById('fileInput').value = '';
    } catch (err) {
      console.error('提取失败:', err);
      setError(`提取失败:${err.message || '未知错误'}`);
    } finally {
      setIsExtracting(false);
    }
  };

代码解析:

3.4 UI 渲染

  return (
    <div style={{ maxWidth: '600px', margin: '50px auto', textAlign: 'center' }}>
      <h1>📄 从 Word 提取文本</h1>
      <p style={{ color: '#666' }}>选择本地的 .doc 或 .docx 文件,提取全部文本内容</p>
      <div style={{ margin: '30px 0' }}>
        <input
          id="fileInput"
          type="file"
          accept=".doc,.docx"
          onChange={handleFileChange}
          disabled={!wasmModule || isExtracting}
          style={{ display: 'none' }}
        />
        <label
          htmlFor="fileInput"
          style={{
            display: 'inline-block',
            padding: '10px 20px',
            background: '#f0f0f0',
            borderRadius: '4px',
            cursor: 'pointer',
            border: '1px solid #ccc',
          }}
        >
          {selectedFile ? `已选:${selectedFile.name}` : '选择 Word 文档'}
        </label>
      </div>
      {selectedFile && (
        <button
          onClick={extractTextFromUploadedFile}
          disabled={!wasmModule || isExtracting}
          style={{
            padding: '12px 30px',
            fontSize: '16px',
            backgroundColor: '#007bff',
            color: '#fff',
            border: 'none',
            borderRadius: '4px',
            cursor: 'pointer',
            marginTop: '10px',
          }}
        >
          {isExtracting ? '提取中...' : '提取并下载文本'}
        </button>
      )}
      {error && (
        <div style={{ marginTop: '20px', color: '#d32f2f', background: '#ffebee', padding: '10px', borderRadius: '4px' }}>
          {error}
        </div>
      )}
      {!wasmModule && !error && (
        <div style={{ marginTop: '20px', color: '#888' }}>⏳ 文档引擎加载中,请稍候...</div>
      )}
    </div>
  );
}
export default App;

UI 部分提供了完整的用户交互反馈:文件选择、加载状态、错误提示和引擎加载进度。

3.5 启动开发服务器

将以上完整 App 组件代码复制到 src/App.js 文件中并保存。在项目根目录执行:

npm start

该命令会启动 React 开发服务器,默认在 http://localhost:3000 打开应用。

点击“选择 Word 文档”按钮,上传本地的 .doc 或 .docx 文件。

点击“提取并下载文本”按钮,稍等片刻即可自动下载提取出的 .txt 文件。

四、进阶技巧 - 提取指定段落或节的文本

如果不需要提取整个文档的文本,可以使用更精细的 API:

const doc = new wasmDoc.Document();
doc.LoadFromFile(fileName);

// 获取第一个节(Section)
const section = doc.Sections.get_Item(0);
// 获取该节中的第一个段落
const paragraph = section.Paragraphs.get_Item(0);
// 提取该段落的文本
const text = paragraph.Text;

五、总结

通过以上示例,可以在浏览器端实现 Word 文档处理能力,让前端文本提取不再依赖后端服务。本文完整拆解了 React 环境下的实现方案,从 WASM 初始化、虚拟文件系统操作,到资源释放与异常处理,覆盖了生产环境所需的全部细节。

Spire.Doc for JavaScript 支持的 Word 文档格式涵盖 Word 97-2003 到 Word 2019 的所有版本,并支持将 DOC/DOCX 文件转换为 TXT、HTML、PDF、图片等多种格式。

以上就是JavaScript实现纯前端提取Word文本的完整教程的详细内容,更多关于JavaScript提取Word文本的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文