跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaScriptNode.js大前端

纯前端实现 Word 文档读取与导出方案详解

概述 本方案支持 Word 文档(.docx)的导入和导出,实现了编辑器与 Office 文档格式之间的无缝转换。整体架构如下: 核心依赖库 | 库名 | 版本 | 用途 | | --- | --- | --- | | mammoth | 1.11.0 | Word 文档导入,将 .docx 转换为 HTML | | docx | 9.1.0 | Word 文档导出,将 JSON 转换为 .doc…

城市逃兵发布于 2026/4/6更新于 2026/10/2588K 浏览
纯前端实现 Word 文档读取与导出方案详解

概述

本方案支持 Word 文档(.docx)的导入和导出,实现了编辑器与 Office 文档格式之间的无缝转换。整体架构如下:

Word .docx 文件 ↓ (导入) mammoth 库解析 ↓ HTML 格式 ↓ Tiptap 编辑器 ↓ JSON Content ↓ (导出) docx 库生成 ↓ Word .docx 文件 
核心依赖库
库名版本用途
mammoth1.11.0Word 文档导入,将 .docx 转换为 HTML
docx9.1.0Word 文档导出,将 JSON 转换为 .docx
markdown-it14.1.0Markdown 文档导入
Word 文档导入
文件位置
  • API 路由: src/app/api/import/route.ts
  • 核心逻辑: src/lib/server/importDocument.ts
1. 导入流程

.docx.md.txt 用户选择文件 FormData 上传文件 验证文件类型? mammoth 解析 markdown-it 解析 纯文本解析 生成 HTML 样式清理 返回给前端 Tiptap 渲染

2. API 接口

端点: POST /api/import

请求格式: multipart/form-data

{
  file: File // 上传的文件对象
}

响应格式:

{
  success: true,
  html: string, // 转换后的 HTML
  format: 'docx' | 'markdown' | 'text', // 原始格式
  warnings?: string[], // 警告信息(如有)
  filename:  
}
string
// 文件名

文件限制:

  • 最大文件大小:10MB
  • 支持格式:.docx, .md, .markdown, .txt
3. Word 文档解析 (mammoth)
核心函数:docxToHtml
async function docxToHtml(buffer: ArrayBuffer): Promise<ImportedDocumentResult> {
  const nodeBuffer = Buffer.from(buffer);
  const { value, messages } = await mammoth.convertToHtml({
    buffer: nodeBuffer,
    {
      // 样式映射:将 Word 样式映射到 HTML 标签
      styleMap: [
        'p[style-name="Heading 1"] => h1:fresh',
        'p[style-name="Heading 2"] => h2:fresh',
        'p[style-name="Heading 3"] => h3:fresh',
        'p[style-name="Heading 4"] => h4:fresh',
      ],
      // 图片处理:转换为 base64 内联图片
      convertImage: mammoth.images.inline(async (image) => {
        const base64 = await image.read('base64');
        return {
          src: `data:${image.contentType};base64,${base64}`,
        };
      }),
    }
  });
  // 清理样式(移除 text-indent 等)
  const sanitized = removeInlineTextIndentStyles(value.trim()) || '<p></p>';
  // 提取警告信息
  const warnings = messages?.filter((message) => message.type === 'warning').map((message) => message.message);
  return {
    format: 'docx',
    html: sanitized,
    warnings: warnings && warnings.length > 0 ? warnings : undefined,
  };
}
样式映射策略

mammoth 通过 styleMap 配置将 Word 内置样式映射到 HTML 标签:

Word 样式HTML 标签说明
Heading 1<h1>一级标题,fresh 表示强制创建新标签
Heading 2<h2>二级标题
Heading 3<h3>三级标题
Heading 4<h4>四级标题
Normal (默认)<p>普通段落

fresh 修饰符: 确保每个样式都生成独立的新标签,避免合并到父元素。

图片处理
convertImage: mammoth.images.inline(async (image) => {
  const base64 = await image.read('base64');
  return {
    src: `data:${image.contentType};base64,${base64}`,
  };
})

工作原理:

  1. mammoth 检测到 Word 文档中的图片
  2. 读取图片二进制数据并转换为 base64 编码
  3. 生成 data URL: data:image/png;base64,iVBORw0KGgo...
  4. 在 HTML 中内联显示,无需外部图片文件

优点:

  • ✅ 所有资源自包含,无需额外请求
  • ✅ 编辑器可直接渲染
  • ✅ 支持离线编辑

缺点:

  • ❌ 大图片会增加文档体积
  • ❌ base64 编码比原始二进制大约 33%
4. 样式清理
removeInlineTextIndentStyles 函数
function removeInlineTextIndentStyles(html: string): string {
  return html.replace(/(style=)(['"])([^'"]*)(\2)/gi, (_match, prefix: string, quote: string, styles: string) => {
    const filtered = styles
      .split(';')
      .map((item) => item.trim())
      .filter((item) => item.length > 0 && !/^text-indent\s*:/i.test(item));
    if (filtered.length === 0) {
      return '';
    }
    return `${prefix}${quote}${filtered.join('; ')}${quote}`;
  });
}

目的: 移除 Word 文档中的 text-indent 样式,避免与编辑器的首行缩进规则冲突。

示例:

<!-- 清理前 -->
<p style="text-indent: 2em;font-size: 14px;">段落内容</p>
<!-- 清理后 -->
<p style="font-size: 14px;">段落内容</p>
5. 纯文本和 Markdown 导入
纯文本导入
function textToHtml(buffer: ArrayBuffer): ImportedDocumentResult {
  const text = normalizeTextContent(buffer).trim();
  // 检测段落分隔符(双换行)
  const hasDoubleBreak = /\n{2,}/.test(text);
  const rawBlocks = hasDoubleBreak ? text.split(/\n{2,}/) : text.split(/\n/);
  const paragraphs = rawBlocks
    .map((block) => block.replace(/\n+/g, '\n').trim())
    .filter(Boolean)
    .map((paragraph) => {
      if (!hasDoubleBreak) {
        return `<p>${escapeHtml(paragraph)}</p>`;
      }
      // 段落内的单换行转换为 <br>
      const lines = paragraph.split('\n').map((line) => escapeHtml(line));
      return `<p>${lines.join('<br>')}</p>`;
    });
  return {
    format: 'text',
    html: paragraphs.join('\n'),
  };
}

目录

  1. 概述
  2. 核心依赖库
  3. Word 文档导入
  4. 文件位置
  5. 1. 导入流程
  6. 2. API 接口
  7. 3. Word 文档解析 (mammoth)
  8. 核心函数:docxToHtml
  9. 样式映射策略
  10. 图片处理
  11. 4. 样式清理
  12. removeInlineTextIndentStyles 函数
  13. 5. 纯文本和 Markdown 导入
  14. 纯文本导入

更多推荐文章

查看全部
  • Android Framework 源码深度解读与进阶开发指南
  • Llama-2-7B 在昇腾 NPU 上的性能测评与部署实践
  • 《Agent Runtime 工程化》第十一章 源码研读方法:11.11 验收标准
  • 应对互联网寒冬:Android开发者如何提升自我
  • 常见降低AIGC检测率工具对比与选择指南
  • Java 常见集合框架详解
  • RS485 收发器在 FPGA 中的应用及毛刺处理
  • 传统解析 vsAI 生成:JAVAXXIX17 处理效率对比
  • C++ STL 容器与 Qt 容器对比及选型建议
  • 大模型人才年薪百万引关注,行业供需现状与技能需求解析
  • C++ 继承进阶:友元、静态成员与菱形继承底层逻辑
  • whisperX 本地化部署与离线语音识别方案
  • Spring Boot 实战:基于 WebSocket 的前后端实时匹配系统实现
  • Spring Cloud 微服务环境与工程搭建指南
  • 程序员必备实用工具与资源网站推荐
  • C++ string 类常用成员函数与全局函数详解
  • FLUX.1 镜像部署指南:内置中文界面与场景优化
  • AI 影响最大的职业 Top10 分析:程序员与 IT 支持为何居首
  • 本地大模型部署:从入门到弃坑的现实复盘
  • OpenClaw 101:本地优先的 AI 智能体部署与实战指南

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online