当前位置: 首页 > news >正文

Java 集成 onlyoffice 预览文件功能

Java 集成 onlyoffice 预览文件功能

准备工作,安装 部署好 onlyoffice 服务,部署时修改密钥为标准的密钥
符合RFC 7518 规范的密钥。

引入一个用于生成 jwt 令牌的 jar

我这里是用的 jjwt(无法使用长度不足32位的密钥,32*8=256)


<dependencies><!-- jjwt --><!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api --><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.13.0</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-impl</artifactId><version>0.13.0</version><scope>runtime</scope></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId><version>0.13.0</version><scope>runtime</scope></dependency>
</dependencies>

官方示例代码的jar 为 prime-jwt;联系官方开发确认是 prime-jwt-1.3.1.jar


<dependency><groupId>com.inversoft</groupId><artifactId>prime-jwt</artifactId><version>1.3.1</version>
</dependency>

使用 prime-jwt 测试结果并不理想,虽然支持非标准密钥,但是生成后的令牌 未能通过onlyoffice 服务器校验,
提供的js 示例 支持非标准密钥可以通过校验。

验证 html

使用 js 示例 验证

<!DOCTYPE html>
<html style="height: 100%;" lang="">
<head><title>ONLYOFFICE 官方示例验证</title><meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body style="height: 100%; margin: 0;">
<div style="height: 100%"><div id="placeholder"></div>
</div>
<script type="text/javascript" src="https://you.onlyService.com/web-apps/apps/api/documents/api.js"></script>
<script>// 封装初始化逻辑async function initEditor() {const config = {"document": {"title": "测试onlyOffice.docx",//不同的文件不能使用相同的key"key": "690acb4889e2ec096645ddf8","fileType": "docx","url": "https://you.file.com/测试onlyOffice.docx"},"documentType": "word","editorConfig": {"coEditing": {"mode": "strict","change": false},"mode": "view",//指定编辑器为中文"lang": "zh"},"width": "100%","height": "100%"};try {// 使用安全的UTF-8编码生成JWTconfig.token = await createJWT(config, 'W0fZRKvsq2YGS4EiUtP8wvd2PEfqHe11');window.docEditor = new DocsAPI.DocEditor("placeholder", config);} catch (error) {console.error("初始化失败:", error);alert("编辑器初始化失败: " + error.message);}}// 修复的JWT生成函数(支持UTF-8字符)async function createJWT(json, secret) {const header = {typ: "JWT",alg: "HS256"};// 使用TextEncoder进行UTF-8编码const encoder = new TextEncoder();const headerData = encoder.encode(JSON.stringify(header));const payloadData = encoder.encode(JSON.stringify(json));// Base64编码(URL安全)const base64EncodeURL = bytes => {return btoa(String.fromCharCode(...bytes)).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');};const encodedHeader = base64EncodeURL(headerData);const encodedPayload = base64EncodeURL(payloadData);// 生成签名const algorithm = {name: "HMAC", hash: "SHA-256"};const key = await crypto.subtle.importKey("raw",encoder.encode(secret),algorithm,false,["sign"]);const signature = await crypto.subtle.sign(algorithm.name,key,encoder.encode(`${encodedHeader}.${encodedPayload}`));return `${encodedHeader}.${encodedPayload}.${base64EncodeURL(new Uint8Array(signature))}`;}// 启动初始化initEditor();
</script>
</body>
</html>

使用其他语言生成的密钥验证

<!DOCTYPE html>
<html style="height: 100%;">
<head><title>ONLYOFFICE Api Documentation</title>
</head>
<body style="height: 100%; margin: 0;">
<div id="placeholder" style="height: 100%"></div>
<script type="text/javascript" src="https://you.onlyService.com/web-apps/apps/api/documents/api.js"></script>
<script type="text/javascript">//一般为调用后端接口,由后端生成 config,之后 用config 生成令牌,并将令牌 设置到 config.token。const config = {"editorConfig": {"mode": "view","coEditing": {"mode": "strict","change": false},//指定编辑器为中文"lang": "zh"},"documentType": "word","document": {"title": "测试onlyOffice.docx",//不同的文件不能使用相同的key"key": "690acb4889e2ec096645ddf8","fileType": "docx","url": "https://you.file.com/测试onlyOffice.docx"},"width": "100%","height": "100%","token": ""}window.docEditor = new DocsAPI.DocEditor("placeholder", config);</script>
</body>
</html>

java 代码

controller
    @PostMapping("onlyForm/{id}")public R<SysFile> onlyForm(@PathVariable("id") String id) {return  sysFileService.onlyForm(id);}
service
    @Overridepublic R<SysFile> onlyForm(String id) {SysFile file = super.findOne(id);if (file == null) {return R.ok();}//生成configMap<String, Object> config = getConfig(file);if(config!=null){//生成令牌String token = OnlyOfficeConfig.getToken(config);config.put("token", token);file.setConfig(config);}return R.ok(file);}public Map<String, Object> getConfig(SysFile file) {//文件类型String fileType = file.getFileType();if (StringUtils.isBlank(fileType)) {return null;}//根据文件类型获取 only中的类型String documentType = OnlyOfficeConfig.getDocumentType(fileType);if (StringUtils.isBlank(documentType)) {return null;}fileType = fileType.substring(1);if (StringUtils.isBlank(fileType)) {return null;}String srcName = file.getSrcName();String url = OnlyOfficeConfig.servicePath + file.getFileurl();Map<String, Object> customClaims = new HashMap<>();Map<String, Object> document = new HashMap<>();customClaims.put("document", document);document.put("key", file.getId());document.put("fileType", fileType);document.put("title", srcName);document.put("url", url);customClaims.put("documentType", documentType);Map<String, Object> editorConfig = new HashMap<>();customClaims.put("editorConfig", editorConfig);Map<String, Object> coEditing = new HashMap<>();editorConfig.put("coEditing", coEditing);coEditing.put("mode", "strict");coEditing.put("change", false);editorConfig.put("mode", "view");customClaims.put("width", "100%");customClaims.put("height", "100%");editorConfig.put("region","china");//重要:指定编辑器页面为中文editorConfig.put("lang","zh");return customClaims;
}
OnlyOfficeConfig 类
/* version 1.8 */
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Date;
import java.util.Map;/*** only office config**/
public class OnlyOfficeConfig {private static final Logger log = LoggerFactory.getLogger(OnlyOfficeConfig.class);/*** 密钥*/public static String secret;/*** 我方服务器请求路径*/public static String servicePath;/*** jjwt key*/public static Key key;/*** 生成 jjwt 的key*/public static void generateKey() {key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));}/*** 获取token* @param customClaims 请求对象* @return token*/public static String getToken(Map<String, Object> customClaims) {String realName = "获取登录用户信息";String token = Jwts.builder().issuer(realName)          // 用户
//                .subject("")           // 主题
//                .audience()                      // 受众配置
//                .add("mobile-app")           // 添加单个受众
//                .add("web-client")           // 添加多个受众
//                .and()                       // 返回父对象继续配置.expiration(new Date(System.currentTimeMillis() + 3600000)) // 1小时过期.notBefore(new Date())           // 立即生效.issuedAt(new Date())            // 签发时间//.id("dfadadsffasdf")                // 唯一令牌ID// 自定义声明.claims(customClaims)            // 批量添加自定义声明// 签名配置.signWith(key).compact();log.info("token:{}",token);return token;}public static String getDocumentType(String fileType) {//fileType = fileType.toLowerCase();switch (fileType) {case ".doc":case ".docm":case ".docx":case ".dot":case ".dotm":case ".dotx":case ".epub":case ".fb2":case ".fodt":case ".htm":case ".html":case ".mht":case ".mhtml":case ".odt":case ".ott":case ".pages":case ".rtf":case ".stw":case ".sxw":case ".txt":case ".wps":case ".wpt":case ".xml":return "word";case ".csv":case ".et":case ".ett":case ".fods":case ".numbers":case ".ods":case ".ots":case ".sxc":case ".xls":case ".xlsb":case ".xlsm":case ".xlsx":case ".xlt":case ".xltm":case ".xltx"://case ".xml":return "cell";case ".dps":case ".dpt":case ".fodp":case ".key":case ".odp":case ".otp":case ".pot":case ".potm":case ".potx":case ".pps":case ".ppsm":case ".ppsx":case ".ppt":case ".pptm":case ".pptx":case ".sxi":return "slide";case ".djvu":case ".docxf":case ".oform":case ".oxps":case ".pdf":case ".xps":return "pdf";case ".vsdm":case ".vsdx":case ".vssm":case ".vssx":case ".vstm":case ".vstx":return "diagram";default:return null;}}
}

vue 代码示例

点击预览,跳转单页面

单页面内容


<template><!-- 这里的高度需要指定,不然高度会有问题 --><div style="height: 100%;"><div id="placeholder"></div></div>
</template><script>export default {name: '',data() {return {id:""}},mounted() {const script = document.createElement('script');script.src = 'https://you.onlyService.com/web-apps/apps/api/documents/api.js';document.head.appendChild(script);this.id = this.$route.query.id;this.initDetail();},methods: {initDetail() {if (!this.id) return;//后端接口let url = `onlyForm${this.id}`this.$post(url).then(result => {if ( result.data && result.data.config) {setTimeout(function () {window.docEditor = new DocsAPI.DocEditor("placeholder", result.data.config);}, 1000)} else {this.$message.warning("当前文件不支持预览!");}});},}}
</script><style>
</style>

关于内网判断

添加一个接口,添加一个只能内网访问的域名,需要 https;将域名指向这个接口
在网关中 添加

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, @NotNull FilterChain filterChain) throws IOException {String requestURI = request.getRequestURI();if (requestURI.startsWith("特定接口")) {response.setHeader("Access-Control-Allow-Origin", "你的web域名");response.setHeader("Access-Control-Allow-Credentials", "true");}//也可以校验 originString origin = request.getHeader("Origin");//判断请求是否来自特定域名 之后再设置 Access-Control-Allow-Origin
}
http://www.dtcms.com/a/582915.html

相关文章:

  • Maven中的配置
  • 网站开发界面设计用什么工具商城建设开发
  • 访问阿里云主机网站免费打广告的平台app
  • docker拉取失败,更换docker的源
  • asp网站验证码不显示莱州网络推广公司
  • Android Gralde补全计划 productFlavors多渠道打包(变体/多客户)
  • 网站建设多少钱网站开发项目经理职责
  • 浙江腾鑫建设集团网站手机如何打开wordpress
  • 算法 day 47 单调栈
  • 一个静态网站开发考虑什么绍兴建设局网站首页
  • 做网站练手项目广东新闻联播回看
  • JavaEE初阶——多线程(8)JUC的常见类
  • 全参数DeepSeek(671B)企业部署方案
  • 柳州网站开发网上申请店铺开网店的流程
  • Java与Swift完整语法对比手册
  • 网站系统环境的搭建微信公众平台小程序二维码怎么生成
  • 做吉祥物设计看什么网站wordpress 开头空格
  • dockerfile一个引号缺失带来的惨案
  • 做电子板报的网站wordpress 汽车租赁
  • 英文网站设计公司建网站的过程
  • 虚拟网站php专业型网站开发服务费会计处理
  • 东莞大朗网站建设公司怎么查看网站死链接
  • 站多多 福州网站建设益阳建设网站
  • 中科数测研究院议题入选Biohacking Village Labs,即将亮相东京CodeBlue大会
  • SpringCloud微服务保护与分布式事务知识点总结
  • Kubernetes脉络:从基础概念到核心架构的认知框架
  • Ascend C核函数执行全流程深潜:从rtKernelLaunch到硬件执行的完整解密
  • 海澜之家的网站建设目标中文官网资源
  • 食品 网站源码外贸出口公司网站建设方案
  • 沈阳建网站如何建设企业人力资源网站