如何在 HTML 页面中嵌入 Office 文档编辑器
|
028-81705109
|
|
微信扫一扫
|

Spire.Cloud 纯前端文档控件

如何在 HTML 页面中嵌入 Office 文档编辑器

在 HTML 页面中嵌入 Web 版 Office 文档编辑器的教程

现代 Web 应用程序越来越多地需要在浏览器中直接查看和编辑 Word、Excel 和 PowerPoint 文件。相比将用户跳转到新页面或外部应用,许多开发者更倾向于将 Office 编辑器直接嵌入网页,使其成为现有界面的一部分,从而提供更加流畅的在线文档处理体验。

然而,从零开始构建一个功能完善的在线文档编辑器并不容易,通常需要处理文档渲染、格式兼容性、编辑交互以及响应式 UI 集成等复杂问题。借助 Spire.OfficeJS,开发者可以使用 JavaScript 快速将基于浏览器的 Office 编辑器集成到 HTML 页面中,而无需在客户端设备上安装 Microsoft Office 等文档处理工具。

本文将演示如何在 HTML 中嵌入文档编辑器,包括页面布局设计、编辑器初始化以及动态文档加载,并提供完整的实用示例。

目录


为什么要在网页中嵌入 Office 编辑器?

将文档编辑器作为页面布局的一部分嵌入,可以实现无缝工作流程并提升用户体验。常见应用场景包括:

  • 文档管理系统(DMS),用户无需离开界面即可查看和编辑文件
  • 集成文件编辑功能的 CRM 或 ERP 平台
  • 需要实时文档编辑的在线协作工具
  • 具有文档预览功能的内部业务仪表板

用户可以直接在当前 Web 界面中处理文档,而无需在单独的应用程序或专用页面中打开文档。

嵌入式与全屏编辑器

有两种常见的集成方式:

方式 描述
全屏编辑器 整个页面专用于文档编辑
嵌入式编辑器 编辑器作为更大 UI 的一部分集成

本教程重点介绍嵌入式方法,即文档编辑器与侧边栏、文件列表、导航菜单和其他应用程序组件协同工作。


环境准备

在集成编辑器之前,请确保具备以下条件:

配置服务器环境

  1. 下载并解压 Spire.OfficeJS 包 并将其解压到本地目录。

  2. 初始化字体

    cd Spire.OfficeJS.Windows_11.5.7
    run_genallfonts.bat

    部署前需要先执行“run_genallfonts.bat”初始化字体,执行后web文件夹下会多出fontsweb文件夹包含基础字体。如果需要新增其它字体,请参阅:如何在 Spire.OfficeJS 前端编辑器中添加自定义字体

    fontsweb文件夹

  3. 启动 Spire.OfficeJS 后端服务

    run_servers.bat

    这将在 http://localhost:3000 上启动编辑器服务

  4. 启动示例服务器(提供示例文档) 示例服务器运行在 http://localhost:3000,示例文档位于 /public/samples/

    如需了解如何在 JavaScript 应用程序中安装和部署 Spire.OfficeJS,请参阅:如何在 JavaScript 中部署 Spire.OfficeJS

环境要求

  • 可从浏览器访问的文档文件
  • 支持 WebAssembly 的现代浏览器

注意: 以下代码示例使用 localhost 地址进行本地开发和测试。在生产环境中,请将其替换为实际的服务器 URL 或域名。


集成的基本页面布局

第一步是设计一个布局,使编辑器仅占据页面的一部分。以下是带有侧边栏和编辑器区域的常见结构:

<!DOCTYPE html>
<html>
<head>
  <title>文档编辑器集成</title>
  <style>
    .app-container {
      display: flex;
      height: 100vh;
    }

    .sidebar {
      width: 250px;
      border-right: 1px solid #ddd;
      padding: 10px;
      background: #f5f5f5;
    }

    .editor-container {
      flex: 1;
      position: relative;
    }
  </style>
</head>
<body>
  <div class="app-container">
    <div class="sidebar">
      <h3>文档列表</h3>
      <ul>
        <li onclick="openDocument('http://localhost:3000/public/samples/sample.docx', 'docx')">示例文档.docx</li>
        <li onclick="openDocument('http://localhost:3000/public/samples/sample.xlsx', 'xlsx')">示例电子表格.xlsx</li>
        <li onclick="openDocument('http://localhost:3000/public/samples/sample.pptx', 'pptx')">示例演示文稿.pptx</li>
      </ul>
    </div>

    <div class="editor-container" id="editor"></div>
  </div>
</body>
</html>

一个简单的嵌入式文档管理界面在打开文档前可能如下所示:

文档管理界面

布局说明

  • 侧边栏显示带有可点击文档名称的文件列表
  • 编辑器容器是一个弹性项目,将托管文档编辑器
  • 编辑器使用 flex: 1 填充剩余空间

这种结构反映了真实世界的应用程序布局,而非简单的演示页面。


将 Office 编辑器嵌入容器

加载 Spire.OfficeJS 脚本并在指定容器内初始化编辑器:

<script src="http://localhost:3000/web/editors/spireapi/SpireCloudEditor.js"></script>

<script>
function initEditor() {
  const config = {
    user: {
      id: 'user1',
      name: '演示用户'
    },
    fileAttrs: {
      sourceUrl: "http://localhost:3000/public/samples/sample.docx",
      fileInfo: {
        ext: "docx",
        name: "示例文档.docx"
      }
    },
    editorAttrs: {
      editorType: "document",
      editorMode: "edit",
      editorWidth: "100%",
      editorHeight: "100%",
      platform: "desktop",
      viewLanguage: "zh",
      canEdit: true,
      canDownload: true,
      canForcesave: true,
      useWebAssemblyDoc: true,
      useWebAssemblyExcel: true,
      useWebAssemblyPpt: true,
      useWebAssemblyPdf: true,
      serverless: {
        useServerless: true,
        baseUrl: "http://localhost:3000",
coAuthorUrl: "http://localhost:8000"  //协同编辑服务
      },
      embedded: {
        saveUrl: "",
        toolbarDocked: 'top'
      },
      events: {
        onDocumentReady: function() {
          console.log('文档已就绪');
        },
        onError: function(event) {
          console.error('编辑器错误:', event);
        },
        onSave: function(data) {
          console.log('文档已保存', data);
          if (data && data.data && data.data.length >= 2) {
            downloadFile(data.data[1], data.data[0]);
          }
        }
      }
    }
  };

  new SpireCloudEditor.OpenApi("editor", config);
}

function downloadFile(file, fileName) {
  const a = document.createElement('a');
  const url = URL.createObjectURL(file);
  a.href = url;
  a.download = fileName;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  URL.revokeObjectURL(url);
}

initEditor();
</script>

初始化后,嵌入式 Office 编辑器将直接加载到目标容器中:

嵌入式编辑器

为帮助快速入门,可以下载本文中使用的完整可运行 HTML 示例:

下载嵌入式编辑器示例

注意:在打开示例编辑器之前,请先启动 Spire.OfficeJS 服务。以上下载演示示例使用 window.location.hostname 动态检测当前主机,因此应通过 HTTP 服务器打开。如需直接在浏览器中预览文件,请将其替换为固定的主机地址。

配置详解

  • user:必需的用户配置,包含自定义设置
  • fileAttrs:文档源 URL 和文件元数据
  • editorAttrs:编辑器行为,包括模式、尺寸和语言

编辑器在 ID 为 "editor"指定容器元素内渲染,使其能够作为 UI 组件运行,而不是接管整个页面。


动态加载和切换文档

在实际应用中,用户需要动态打开不同的文件。可以通过使用新配置重新初始化编辑器来实现:

let editorInstance = null;

function openDocument(sourceUrl, ext) {
  const fileName = sourceUrl.split('/').pop();if (editorInstance){editorInstance.destroy();}const container = document.getElementById("editor");container.innerHTML = "";const config ={user:{id:'user1',name:'演示用户'},fileAttrs:{sourceUrl:sourceUrl,fileInfo:{ext:ext,name:fileName}},editorAttrs:{editorType:getEditorType(ext),editorMode:"edit",editorWidth:"100%",editorHeight:"100%",platform:"desktop",viewLanguage:"zh",canEdit:true,canDownload:true,canForcesave:true,useWebAssemblyDoc:true,useWebAssemblyExcel:true,useWebAssemblyPpt:true,useWebAssemblyPdf:true,serverless:{useServerless:true,baseUrl:"http://localhost:3000",coAuthorUrl:"http://localhost:8000" //协同编辑服务地址},embedded:{saveUrl:"",toolbarDocked:'top'},events:{onSave:function(data){if (data && data.data && data.data.length>= 2){downloadFile(data.data[1],data.data[0]);}}}}};editorInstance = new SpireCloudEditor.OpenApi("editor",config);}function getEditorType(ext){const extLower = ext.toLowerCase();switch (extLower){case 'docx':case 'doc':case 'rtf':case 'txt':case 'odt':return 'document';case 'xlsx':case 'xls':case 'csv':case 'ods':return 'spreadsheet';case 'pptx':case 'ppt':case 'odp':return 'presentation';default:return 'document';}}

工作原理

  • 点击侧边栏中的文件会触发 openDocument,传入文件 URL 和扩展名
  • 销毁之前的编辑器实例并清空容器
  • 编辑器使用选定的文档重新加载
  • 无需刷新页面,保持应用程序状态

此模式对于构建交互式文档管理系统至关重要。

文档切换的最佳实践

在动态切换文档时,正确的清理可以避免 UI 问题:

错误处理和加载状态

始终使用 try-catch 进行错误处理,并考虑添加加载指示器:

let editorInstance = null;async function openDocument(sourceUrl,ext){try{if (editorInstance){editorInstance.destroy();}const container = document.getElementById("editor");container.innerHTML = "";const config ={};editorInstance = new SpireCloudEditor.OpenApi("editor",config);}catch (error){console.error('加载文档失败:',error);}}

关键点:

  • 在创建新实例之前始终销毁旧实例
  • 清空容器元素以防止 UI 冲突
  • 使用 try-catch 实现健壮的错误处理

自定义编辑器行为

可以使用 editorAttrs中的配置选项微调编辑器的行为。

只读模式

将编辑器设置为仅查看模式:

editorAttrs:{editorMode:"view",isReadOnly:true}

控制用户权限

限制特定操作:

editorAttrs:{canEdit:false,canDownload:false,canComment:true,canPrint:true}

更改 UI 语言

通过设置界面语言支持国际化:

editorAttrs:{viewLanguage:"en"}

支持的语言包括英语("en")和中文("zh")。

配置保存功能

在无服务器模式下,保存通过 onSave事件回调处理:

editorAttrs:{embedded:{saveUrl:"",// 在无服务器模式下保持为空 toolbarDocked:'top'},events:{onSave:function(data){console.log('文档已保存',data);if (data &&data.data &&data.data.length >= 2){// data.data[0] = 文件名,data.data[1] = 文件 blob downloadFile(data.data[1],data.data[0]);}}}}function downloadFile(file,fileName){const a = document.createElement('a');const url = URL.createObjectURL(file);a.href = url;a.download = fileName;document.body.appendChild(a);a.click();document.body.removeChild(a);URL.revokeObjectURL(url);}

当用户点击保存时,文档将自动下载到本地计算机。

动态协议配置

为支持 HTTP 和 HTTPS 环境,使用动态协议检测:

const currentHost = window.location.hostname;const currentProtocol = window.location.protocol;const baseUrl = `${currentProtocol}//${currentHost}:3000`;const exampleBaseUrl = `${currentProtocol}//${currentHost}:3000`;const coAuthorUrl = `${currentProtocol}//${currentHost}:8000`;

这可以防止在页面通过 HTTPS 提供服务时出现混合内容错误。

上传本地文件

用户可以上传本地文档进行编辑:

<input type="file"id="fileInput"accept=".docx,.xlsx,.pptx,.doc,.xls,.ppt"onchange="handleFileUpload(event)">
async function handleFileUpload(event){const file = event.target.files[0];const fileName = file.name;const ext = fileName.split('.').pop().toLowerCase();const fileData = await new Promise((resolve) =>{const reader = new FileReader();reader.onload = (e) =>resolve(e.target.result);reader.readAsArrayBuffer(file);});const config ={user:{id:'user1',name:'演示用户'},fileAttrs:{sourceUrl:'upload://' + fileName,fileInfo:{ext,name:fileName}},editorAttrs:{editorType:getEditorType(ext),serverless:{useServerless:true,baseUrl:baseUrl,coAuthorUrl:coAuthorUrl,//协同编辑服务 fileData:fileData // 直接传递文件数据}}};editorInstance = new SpireCloudEditor.OpenApi("editor",config);}

将编辑器集成到现有业务系统

在大多数实际场景中,在线文档编辑器并非整个应用程序,而是作为大型业务系统中的一个模块运行。

典型的集成模式包括:

  • CRM 系统,包含合同编辑和提案生成功能
  • ERP 系统,包含发票审查和报告修改功能
  • 文档管理系统(DMS),包含嵌入式预览和编辑工作流
  • 客户门户,包含可下载和可编辑的表单
  • 内部协作平台,结合文档编辑与聊天、评论和版本控制

由于基于浏览器的 Office 编辑器挂载到标准 DOM 容器中,它可以与以下内容无缝共存:

  • 侧边栏和导航菜单
  • 文件树和文件夹结构
  • 多文档编辑的标签页系统
  • 聊天面板和评论线程
  • 仪表板和分析小部件

这种模块化架构允许开发者构建丰富的以文档为中心的应用程序,而不会影响现有的 UI 模式或用户工作流。


框架集成(React、Vue、Angular)

虽然示例使用纯 JavaScript,但相同的概念也适用于现代框架。关键原则保持不变:在组件挂载后初始化编辑器,并将其渲染到 DOM 容器中。

React

useEffect(() =>{new SpireCloudEditor.OpenApi("editor-container",config);},[]);

Vue

mounted(){new SpireCloudEditor.OpenApi("editor-container",config);}

Angular

ngAfterViewInit():void{new SpireCloudEditor.OpenApi("editor-container",config);}

有关完整的框架特定设置和部署说明,请参阅专门的集成指南:


常见集成问题

以下是开发者遇到的常见问题及其解决方案:

编辑器无法加载

  • 原因:后端服务未运行或脚本 URL 不正确
  • 解决方案:验证服务是否在端口 3000 上运行,并使用正确的脚本路径:http://localhost:3000/web/editors/spireapi/SpireCloudEditor.js

脚本加载失败(CORS 错误)

  • 原因:直接使用 file://协议打开 HTML 文件
  • 解决方案:启动本地 HTTP 服务器(python -m http.server 8080npx http-server -p 8080)并通过 http://localhost:8080/your-file.html访问

文件加载失败

  • 原因:文档 URL 无法访问或被 CORS 阻止
  • 解决方案:确保 sourceUrl可通过 HTTP 公开访问。将占位符 URL(如 https://example.com/)替换为真实可访问的文档 URL

/doc