需求场景:实现文档的在线编辑,团队协作
总结:两个接口 + 前端页面 + 配置项
接口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内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论