OnlyOffice文档服务器安装及集成使用


0、前言

先摘一段官网的描述:ONLYOFFICE 文档 是一个开源办公套件,包括文本文档、电子表格、演示文稿和可填写表单的编辑器。 它提供以下功能:

  • 创建、编辑和查看文本文档、电子表格、演示文稿和可填写表单
  • 与其他队友实时协作处理文件。

官网文档中文:
https://api.onlyoffice.com/zh/editors/basic
官网文档英文:
https://api.onlyoffice.com/editors/basic

在线效果如:
word:
在这里插入图片描述

excel:
在这里插入图片描述

ppt:
在这里插入图片描述

一、安装

1.使用docker安装

创建安装目录

mkdir /app/onlyoffice/DocumentServer/logs -p
mkdir /app/onlyoffice/DocumentServer/data -p
mkdir /app/onlyoffice/DocumentServer/lib -p
mkdir /app/onlyoffice/DocumentServer/db -p

下载镜像

docker pull onlyoffice/documentserver

启动镜像,这里以8088端口对外进行服务,可自行修改

docker run -i -t -d -p 8088:80 --restart=always \
    -v /app/onlyoffice/DocumentServer/logs:/var/log/onlyoffice  \
    -v /app/onlyoffice/DocumentServer/data:/var/www/onlyoffice/Data  \
    -v /app/onlyoffice/DocumentServer/lib:/var/lib/onlyoffice \
    -v /app/onlyoffice/DocumentServer/db:/var/lib/postgresql -e JWT_SECRET=my_jwt_secret onlyoffice/documentserver

2.开启防火墙

将上面的8088端口开放提供服务

firewall-cmd --zone=public --add-port=8088/tcp --permanent
firewall-cmd --reload

3.配置

启动docker后要过一小段时间,通过docker ps 查看已经运行的dockerId,复制出来后,执行下面的两条命令:

sudo docker exec {
    
    onlyOffice Docker ID}  sudo supervisorctl start ds:example
sudo docker exec {
    
    onlyOffice Docker ID} sudo sed 's,autostart=false,autostart=true,' -i /etc/supervisor/conf.d/ds-example.conf

示例如:
sudo docker exec a6caa73db3f3 sudo supervisorctl start ds:example
sudo docker exec a6caa73db3f3 sudo sed 's,autostart=false,autostart=true,' -i /etc/supervisor/conf.d/ds-example.conf

4.访问测试

http://IP:8088/

在这里插入图片描述
可以通过自带的example应用进行测试:http://192.168.56.101:8088/example/

在这里插入图片描述
看到以上截图,即安装完成了。

二、应用集成

以上安装好OnlyOffice并通过example进行体验在线编辑功能,但如果需要在我们的应用系统中正式使用,还需要进行相应的程序集成,集成主要分前端和后台接口两部分。

1.前端集成(React)

参考文档:
https://api.onlyoffice.com/zh/editors/react

(1).安装@onlyoffice/document-editor-react

yarn add @onlyoffice/document-editor-react

(2).使用 ONLYOFFICE 文档 React 组件

以下为我写的页面样例文件

index.less

html,
body {
    
    
    margin: 0;
    padding: 0;
}

.docx-editor-wrapper {
    
    
    height: 100vh;
    overflow: hidden;
}

OnlyOfficeEditor组件代码:

import React from 'react';
import {
    
     DocumentEditor } from "@onlyoffice/document-editor-react";
import './index.less';

const OnlyOfficeEditor = () => {
    
    

    const onDocumentReady = (event) => {
    
    
        // 请输入函数体代码
        console.log("Document is loaded", event);
    };

    return (
        <div className='docx-editor-wrapper'>

            <DocumentEditor
                id="docxEditor"
                documentServerUrl="http://192.168.56.101:8088"
                config={
    
    {
    
    
                    "document": {
    
    
                        "fileType": "docx",
                        "key": "Khirz6zTPdf2dsaazx",
                        "title": "Example Document Title.docx",
                        "url": "http://192.168.56.1:8888/getFile",
                        "permissions": {
    
    
                            "comment": true,
                            "copy": true,
                            "download": true,
                            "edit": true,
                            "print": true,
                            "fillForms": true,
                            "modifyFilter": true,
                            "modifyContentControl": true,
                            "review": true,
                            "commentGroups": {
    
    }
                        }
                    },
                    "documentType": "word", 
                    "type": "mobile", //mobile或者desktop,移动端还是桌面端效果
                    "editorConfig": {
    
    
                        "mode": "edit",
                        "lang": "zh-CN",
                        "callbackUrl": "http://192.168.56.1:8888/callback",
                        "user": {
    
    
                            "id": "liu",
                            "name": "liu"
                        },
                    },
                }}
                events_onDocumentReady={
    
    onDocumentReady}
            />
        </div>
    );
};
export default OnlyOfficeEditor;

重要属性说明:
documentServerUrl: 在线编辑文档服务器的地址(IP和端口)
config.document.key: 定义服务用来识别文档的唯一文档标识符。如果发送了已知key,则将从缓存中获取文档。 每次编辑和保存文档时,都必须重新生成key。 文档 url 可以用作 key,但不能使用特殊字符,长度限制为 128 个符号。
config.document.url:定义存储查看或编辑的源文档的绝对URL,自己写的接口用于获取源始文件提供给在线编辑文档服务器(见Java的实现部分)。
config.editorConfig.callbackUrl:指定文档存储服务回调的绝对地址,即自己写的后台接口处理器,通过此接口进行回调保存处理编辑后的文件(见Java的实现部分)。

其他参数详细参考此文档说明:https://api.onlyoffice.com/zh/editors/config

在App.js中引用OnlyOfficeEditor组件

import React from 'react';
import OnlyOfficeEditor from 'src/components/onlyOfficeEditor';

const App = () => {
    
    
  return (
    <div className='app'>
      <OnlyOfficeEditor />
    </div>
  )
};

export default App;

2.后台集成(Java)

(1) getFile接口

通过此接口提供给文档编辑服务器进行文档下载。

(2) callback接口

通过此接口提供进行在线保存后的文档处理。

官网参考:https://api.onlyoffice.com/zh/editors/callback

在回调接口中status=2时进行文件的保存处理

(3) getFile接口和callback接口代码

OnlyOfficeController.java中包含上面的两个接口代码

package cn.ljhua.onlyoffice.controller;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.Collections;

import javax.servlet.http.HttpServletResponse;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import cn.ljhua.onlyoffice.utils.HttpsKitWithProxyAuth;
import lombok.Getter;
import lombok.Setter;

/**
 * @author liujh
 */
@RestController
public class OnlyOfficeController {
    
    

    private static final String FILE_PATH = "D:/temp/1.docx"; //这里仅写死路径测试

    @CrossOrigin(origins = "*", methods = {
    
    RequestMethod.GET, RequestMethod.OPTIONS})
    @GetMapping("/getFile")
    public ResponseEntity<byte[]> getFile(HttpServletResponse response) throws IOException {
    
    
    	
        File file = new File(FILE_PATH);
        FileInputStream fileInputStream = null;
        InputStream fis = null;
        try {
    
    
        	fileInputStream = new FileInputStream(file);
            fis = new BufferedInputStream(fileInputStream);
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            // 替换为实际的文档名称
            headers.setContentDispositionFormData("attachment", URLEncoder.encode(file.getName(), "UTF-8"));
            return new ResponseEntity<>(buffer, headers, HttpStatus.OK);
        } catch (Exception e) {
    
    
            throw new RuntimeException("e -> ", e);
        } finally {
    
    
        	
        	try {
    
    
				if(fis != null) fis.close();
			} catch (Exception e) {
    
    
				
			}
        	
        	try {
    
    
				if(fileInputStream != null) fileInputStream.close();
			} catch (Exception e) {
    
    
				
			}
        	
        }
        
    }

    @CrossOrigin(origins = "*", methods = {
    
    RequestMethod.GET,RequestMethod.POST, RequestMethod.OPTIONS})
    @PostMapping("/callback")
    public ResponseEntity<Object> handleCallback(@RequestBody CallbackData callbackData) {
    
    

    	//状态监听
        //参见https://api.onlyoffice.com/editors/callback
        Integer status = callbackData.getStatus();
        switch (status) {
    
    
            case 1: {
    
    
                //document is being edited  文档已经被编辑
                break;
            }
            case 2: {
    
    
                //document is ready for saving,文档已准备好保存
            	System.out.println("document is ready for saving");
                String url = callbackData.getUrl();
                try {
    
    
                    saveFile(url); //保存文件
                } catch (Exception e) {
    
    
                    System.out.println("保存文件异常");
                }
                System.out.println("save success.");
                break;
            }
            case 3: {
    
    
                //document saving error has occurred,保存出错
                break;
            }
            case 4: {
    
    
                //document is closed with no changes,未保存退出
                break;
            }
            case 6: {
    
    
                //document is being edited, but the current document state is saved,编辑保存
            }
            case 7: {
    
    
                //error has occurred while force saving the document. 强制保存文档出错
            }
            default: {
    
    

            }
        }
        
        // 返回响应
        return ResponseEntity.<Object>ok(Collections.singletonMap("error", 0));

    }

    public void saveFile(String downloadUrl) throws URISyntaxException, IOException {
    
    
    	
        HttpsKitWithProxyAuth.downloadFile(downloadUrl, FILE_PATH);
        
    }

    @Setter
    @Getter
    public static class CallbackData  {
    
    
        /**
         * 用户与文档的交互状态。0:用户断开与文档共同编辑的连接;1:新用户连接到文档共同编辑;2:用户单击强制保存按钮
         */
//        @IsArray()
//        actions?:IActions[] =null;

        /**
         * 字段已在 4.2 后版本废弃,请使用 history 代替
         */
        Object changeshistory;

        /**
         * 文档变更的历史记录,仅当 status 等于 2 或者 3 时该字段才有值。其中的 serverVersion 字段也是 refreshHistory 方法的入参
         */
        Object history;

        /**
         * 文档编辑的元数据信息,用来跟踪显示文档更改记录,仅当 status 等于 2 或者 2 时该字段才有值。该字段也是 setHistoryData(显示与特定文档版本对应的更改,类似 Git 历史记录)方法的入参
         */
        String changesurl;

        /**
         * url 字段下载的文档扩展名,文件类型默认为 OOXML 格式,如果启用了 assemblyFormatAsOrigin(https://api.onlyoffice.com/editors/save#assemblyFormatAsOrigin) 服务器设置则文件以原始格式保存
         */
        String filetype;

        /**
         * 文档强制保存类型。0:对命令服务(https://api.onlyoffice.com/editors/command/forcesave)执行强制保存;1:每次保存完成时都会执行强制保存请求,仅设置 forcesave 等于 true 时生效;2:强制保存请求由计时器使用服务器中的设置执行。该字段仅 status 等于 7 或者 7 时才有值
         */
        Integer forcesavetype;

        /**
         * 文档标识符,类似 id,在 Onlyoffice 服务内部唯一
         */
        String key;

        /**
         * 文档状态。1:文档编辑中;2:文档已准备好保存;3:文档保存出错;4:文档没有变化无需保存;6:正在编辑文档,但保存了当前文档状态;7:强制保存文档出错
         */
        Integer status;

        /**
         * 已编辑文档的链接,可以通过它下载到最新的文档,仅当 status 等于 2、3、6 或 7 时该字段才有值
         */
        String url;

        /**
         * 自定义参数,对应指令服务的 userdata 字段
         */
        Object userdata;

        /**
         * 打开文档进行编辑的用户标识列表,当文档被修改时,该字段将返回最后编辑文档的用户标识符,当 status 字段等于 2 或者 6 时有值
         */
        String[] users;

        /**
         * 最近保存时间
         */
        String lastsave;

        /**
         * 加密令牌
         */
        String token;
    }
}

三、其他问题

1. 该文件版本已变,该页面将被重新加载

出现该文件版本已变,该页面将被重新加载或者the file version has been changed. the page will be reload.可能是因为你使用的key进行了回调处理,会被认为改变,

在这里插入图片描述
解决:更换新的key,即以下面的key参数进行过callback处理后后就需要更新了,不能一直用同一个。
在这里插入图片描述

四、源码下载

github: https://github.com/jxlhljh/onlyOfficeTest.git
gitee: https://gitee.com/jxlhljh/onlyOfficeTest.git

猜你喜欢

转载自blog.csdn.net/jxlhljh/article/details/133700965
今日推荐