Java集成Onlyoffice的示例代码及场景分析
作者:想要变瘦的小码头
这篇文章主要介绍了Java集成Onlyoffice的示例代码及场景分析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
需求场景:实现文档的在线编辑,团队协作
总结:两个接口 + 前端页面 + 配置项
接口1:一个接口,将onlyoffice前端需要的配置项返回给前端(文档地址、是否编辑模式...)
前端:接受配置项,集成onlyoffice的js文件,展示文档
接口2:一个回调接口,用于onlyoffice前端的文件保存后的调用方法
一些配置项:application 里面配置 服务器的地址,token 等 ,maven 引入依赖。
文章结尾提供官方示例代码:
注意:
1、docs-integration-sdk 2024年12月,国内腾讯的中央仓库下不了,我不想换镜像,就注释掉,用的离线包。
2、加了一个pom 的依赖,不加启动报错

<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency>
接口1:文档地址必须可以让onlyofficeu所在的服务器可以访问到,可以是本地磁盘的映射,可以是 MINIO。文档应当还有一个唯一的Key;
public String index(@RequestParam("fileName") final String fileName,
@RequestParam(value = "action", required = false) final String actionParam,
@RequestParam(value = "type", required = false) final String typeParam,
@RequestParam(value = "actionLink", required = false) final String actionLink,
@CookieValue(value = "uid") final String uid,
@CookieValue(value = "ulang") final String lang,
final Model model) throws JsonProcessingException {
Action action = null;
Type type = Type.DESKTOP;
Locale locale = new Locale("en");
if (actionParam != null) {
action = Action.valueOf(actionParam);
}
if (typeParam != null) {
type = Type.valueOf(typeParam.toUpperCase());
}
List<String> langsAndKeys = Arrays.asList(langs.split("\\|"));
for (String langAndKey : langsAndKeys) {
String[] couple = langAndKey.split(":");
if (couple[0].equals(lang)) {
String[] langAndCountry = couple[0].split("-");
locale = new Locale(langAndCountry[0], langAndCountry.length > 1 ? langAndCountry[1] : "");
}
}
Optional<User> optionalUser = userService.findUserById(Integer.parseInt(uid));
// if the user is not present, return the ONLYOFFICE start page
if (!optionalUser.isPresent()) {
return "index.html";
}
Config config = configService.createConfig(
fileName,
action,
type
);
JSONObject actionData = null;
if (actionLink != null && !actionLink.isEmpty()) {
actionData = new JSONObject(actionLink);
}
config.getEditorConfig().setActionLink(actionData);
config.getEditorConfig().setLang(locale.toLanguageTag());
model.addAttribute("model", config);
// create the document service api URL and add it to the model
model.addAttribute("docserviceApiUrl", urlManager.getDocumentServerApiUrl());
// get an image and add it to the model
model.addAttribute("dataInsertImage", getInsertImage());
// get a document for comparison and add it to the model
model.addAttribute("dataDocument", getCompareFile());
// get recipients data for mail merging and add it to the model
model.addAttribute("dataSpreadsheet", getSpreadsheet());
// get user data for mentions and add it to the model
model.addAttribute("usersForMentions", getUserMentions(uid));
model.addAttribute("usersInfo", getUsersInfo(uid));
// get user data for protect and add it to the model
model.addAttribute("usersForProtect", getUserProtect(uid));
return "editor.html";
}接口2:回调保存,其中的 {\"error\":\"0\"} 是告诉onlyOffice回调接口是没问题的,这样就可以在线编辑文档了,否则的话会弹出窗口说明。
public String track(final HttpServletRequest request, // track file changes
@RequestParam("fileName") final String fileName,
@RequestParam("userAddress") final String userAddress,
@RequestBody final Callback body) {
Callback callback;
try {
String bodyString = objectMapper
.writeValueAsString(body); // write the request body to the object mapper as a string
if (bodyString.isEmpty()) { // if the request body is empty, an error occurs
throw new RuntimeException("{\"error\":1,\"message\":\"Request payload is empty\"}");
}
String authorizationHeader = request.getHeader(settingsManager.getSecurityHeader());
callback = callbackService.verifyCallback(body, authorizationHeader);
callbackService.processCallback(callback, fileName);
} catch (Exception e) {
String message = e.getMessage();
if (!message.contains("\"error\":1")) {
e.printStackTrace();
}
return message;
}
return "{\"error\":\"0\"}";
}前端展示
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" />
<!--
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
-->
<title>ONLYOFFICE</title>
<link rel="icon" th:href="@{/css/img/{icon}.ico(icon=${model.getDocumentType()})}" rel="external nofollow" type="image/x-icon"/>
<link rel="stylesheet" type="text/css" href="css/editor.css" rel="external nofollow" />
<script type="text/javascript" th:src="@{${docserviceApiUrl}}"></script>
<script th:inline="javascript">
var docEditor;
var config;
var innerAlert = function (message, inEditor) {
if (console && console.log)
console.log(message);
if (inEditor && docEditor)
docEditor.showMessage(message);
};
// the application is loaded into the browser
var onAppReady = function () {
innerAlert("Document editor ready");
};
// the document is modified
var onDocumentStateChange = function (event) {
var title = document.title.replace(/\*$/g, "");
document.title = title + (event.data ? "*" : "");
};
// the user is trying to switch the document from the viewing into the editing mode
var onRequestEditRights = function () {
location.href = location.href.replace(RegExp("\&?action=\\w+", "i"), "") + "&action=edit";
};
// an error or some other specific event occurs
var onError = function (event) {
if (event) innerAlert(event.data);
};
// the document is opened for editing with the old document.key value
var onOutdatedVersion = function (event) {
location.reload(true);
};
// replace the link to the document which contains a bookmark
var replaceActionLink = function(href, linkParam) {
var link;
var actionIndex = href.indexOf("&actionLink=");
if (actionIndex != -1) {
var endIndex = href.indexOf("&", actionIndex + "&actionLink=".length);
if (endIndex != -1) {
link = href.substring(0, actionIndex) + href.substring(endIndex) + "&actionLink=" + encodeURIComponent(linkParam);
} else {
link = href.substring(0, actionIndex) + "&actionLink=" + encodeURIComponent(linkParam);
}
} else {
link = href + "&actionLink=" + encodeURIComponent(linkParam);
}
return link;
}
// the user is trying to get link for opening the document which contains a bookmark, scrolling to the bookmark position
var onMakeActionLink = function (event) {
var actionData = event.data;
var linkParam = JSON.stringify(actionData);
docEditor.setActionLink(replaceActionLink(location.href, linkParam));
};
// the meta information of the document is changed via the meta command
var onMetaChange = function (event) {
if (event.data.favorite !== undefined) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite);
}
innerAlert("onMetaChange: " + JSON.stringify(event.data));
};
var dataInsertImage = [[${dataInsertImage}]];
// the user is trying to insert an image by clicking the Image from Storage button
var onRequestInsertImage = function(event) {
const temp = Object.assign({}, {"c": event.data.c}, dataInsertImage);
docEditor.insertImage(temp);
};
var dataDocument = [[${dataDocument}]];
// the user is trying to select document for comparing by clicking the Document from Storage button
var onRequestSelectDocument = function(event) {
const temp = Object.assign({"c": event.data.c}, JSON.parse(dataDocument));
docEditor.setRequestedDocument(temp);
};
var dataSpreadsheet = [[${dataSpreadsheet}]];
// the user is trying to select recipients data by clicking the Mail merge button
var onRequestSelectSpreadsheet = function (event) {
const temp = Object.assign({"c": event.data.c}, JSON.parse(dataSpreadsheet));
docEditor.setRequestedSpreadsheet(temp);
};
config = [[${model}]];
if (config.editorConfig.user.name == "Anonymous") {
config.editorConfig.user.name = "";
}
var onRequestSaveAs = function (event) { // the user is trying to save file by clicking Save Copy as... button
var title = event.data.title;
var url = event.data.url;
var data = {
title: title,
url: url
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "saveas");
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
innerAlert(JSON.parse(xhr.responseText).file, true);
}
};
var onRequestRename = function(event) { // the user is trying to rename file by clicking Rename... button
innerAlert("onRequestRename: " + JSON.stringify(event.data));
var newfilename = event.data;
var data = {
fileName: newfilename,
fileKey: config.document.key,
fileType: config.document.fileType
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "rename");
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
}
};
var onRequestOpen = function(event) { // user open external data source
innerAlert("onRequestOpen");
var windowName = event.data.windowName;
requestReference(event.data, function (data) {
if (data.error) {
var winEditor = window.open("", windowName);
winEditor.close();
innerAlert(data.error, true);
return;
}
var link = data.link;
window.open(link, windowName);
});
};
var onRequestReferenceData = function(event) { // user refresh external data source
innerAlert("onRequestReferenceData");
requestReference(event.data, function (data) {
docEditor.setReferenceData(data);
});
};
var requestReference = function(data, callback) {
innerAlert(data);
let xhr = new XMLHttpRequest();
xhr.open("POST", "reference");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
callback(JSON.parse(xhr.responseText));
}
};
var onRequestHistory = function () {
var xhr = new XMLHttpRequest();
xhr.open("GET", "history?fileName=" + config.document.title, false);
xhr.send();
if (xhr.status == 200) {
var historyInfo = JSON.parse(xhr.responseText);
docEditor.refreshHistory(historyInfo);
}
};
var onRequestHistoryData = function (event) {
var version = event.data;
var historyDataUri = "historydata?fileName=" + config.document.title
+ "&version=" + version;
var xhr = new XMLHttpRequest();
xhr.open("GET", historyDataUri, false);
xhr.send();
if (xhr.status == 200) {
var historyData = JSON.parse(xhr.responseText);
docEditor.setHistoryData(historyData);
}
};
var onRequestHistoryClose = function() {
document.location.reload();
};
function onRequestRestore(event) {
const query = new URLSearchParams(window.location.search)
const payload = {
fileName: query.get('fileName'),
version: event.data.version
}
const request = new XMLHttpRequest()
request.open('PUT', 'restore')
request.setRequestHeader('Content-Type', 'application/json')
request.send(JSON.stringify(payload))
request.onload = function () {
const response = JSON.parse(request.responseText);
if (response.success && !response.error) {
var historyInfoUri = "history?fileName=" + config.document.title;
var xhr = new XMLHttpRequest();
xhr.open("GET", historyInfoUri, false);
xhr.send();
if (xhr.status == 200) {
var historyInfo = JSON.parse(xhr.responseText);
docEditor.refreshHistory(historyInfo);
}
} else {
innerAlert(response.error);
}
}
};
var onRequestUsers = function (event) {
if (event && event.data) {
var c = event.data.c;
}
switch (c) {
case "info":
users = [];
var allUsers = [[${usersInfo}]];
for (var i = 0; i < event.data.id.length; i++) {
for (var j = 0; j < allUsers.length; j++) {
if (allUsers[j].id == event.data.id[i]) {
users.push(allUsers[j]);
break;
}
}
}
break;
case "protect":
var users = [[${usersForProtect}]];
break;
default:
users = [[${usersForMentions}]];
}
docEditor.setUsers({
"c": c,
"users": users,
});
};
var onRequestSendNotify = function(event) { // the user is mentioned in a comment
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
config.width = "100%";
config.height = "100%";
config.events = {
"onAppReady": onAppReady,
"onDocumentStateChange": onDocumentStateChange,
"onError": onError,
"onOutdatedVersion": onOutdatedVersion,
"onMakeActionLink": onMakeActionLink,
"onMetaChange": onMetaChange,
"onRequestInsertImage": onRequestInsertImage,
"onRequestSelectDocument": onRequestSelectDocument,
"onRequestSelectSpreadsheet": onRequestSelectSpreadsheet
};
if (config.editorConfig.user.id != 4) {
// add mentions for not anonymous users
config.events['onRequestUsers'] = onRequestUsers;
config.events['onRequestSaveAs'] = onRequestSaveAs;
// the user is mentioned in a comment
config.events['onRequestSendNotify'] = onRequestSendNotify;
// prevent file renaming for anonymous users
config.events['onRequestRename'] = onRequestRename;
config.events['onRequestReferenceData'] = onRequestReferenceData;
// prevent switch the document from the viewing into the editing mode for anonymous users
config.events['onRequestEditRights'] = onRequestEditRights;
config.events['onRequestOpen'] = onRequestOpen;
config.events['onRequestHistory'] = onRequestHistory;
config.events['onRequestHistoryData'] = onRequestHistoryData;
if (config.editorConfig.user.id != 3) {
config.events['onRequestHistoryClose'] = onRequestHistoryClose;
config.events['onRequestRestore'] = onRequestRestore;
}
}
var сonnectEditor = function () {
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
};
if (window.addEventListener) {
window.addEventListener("load", сonnectEditor);
} else if (window.attachEvent) {
window.attachEvent("load", сonnectEditor);
}
</script>
</head>
<body>
<div class="form">
<div id="iframeEditor"></div>
</div>
</body>
</html>完整代码可以下载,不搞VIP、付费

到此这篇关于Java集成Onlyoffice的文章就介绍到这了,更多相关Java集成Onlyoffice内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
