这个已是好几个月前做的,好多细节已记得不那边清楚了。今天部署到环境还遇到不少问题。总结下。
1、office 文件实现在线预览的一般思路就是,将文件转pdf,在通过pdf.js 实现在线浏览。这其中转pdf 各个工具转换的效果有些差异,存在走样问题。
2、另一种思路是通过脚本调用office 的转换pdf功能,这种效果最好,高保真。但就是会麻烦些,依赖office 工具。
3、如果还要部署到Linux上使用哪就只能用开源的办公软件 openoffice 了。
4、jodconverter 能很好的调用openoffice 工具转换 配置也相对比较简单。
效果图:
springboot 默认集成了jodconverter 所有应用起来很方便
yml 中加入如下配置就可以了
jodconverter:
enabled: true #注意这个开关,今天部署时就遇到这个问题,排查好久才发现。
officeHome: C:Program Files (x86)OpenOffice 4
portNumbers: 8101,8102,8103,8104,8105
maxTasksPerProcess: 5
核心代码:
public boolean office2pdf(FileEntity fileEntity, String suffix) { LOG.info("call office to pdf ,file info:" + fileEntity.toString()); File file = new File(fileEntity.getAbsolute_path()); if (file.exists() && file.isFile()) { LOG.info("call office to pdf ,find file info:" + fileEntity.toString()); try { File pdfFile = new File(file.getParentFile(), fileEntity.getPrn() + suffix); if (!pdfFile.exists()) { DocumentConverter documentConverter = szAppConfig.getBeanByClass(DocumentConverter.class); documentConverter.convert(file).to(pdfFile).execute(); if (".html".equalsIgnoreCase(suffix)) { try { String htmlFormant = "<script src="" + sz_ng_root_path + "/commons/js/333614537928.js"></script> " + " <STYLE> " + " " + " BODY, DIV, TABLE, THEAD, TBODY, TFOOT, TR, TH, TD, P { " + " font-family: "微软雅黑"; " + " font-size: x-small " + " } " + " " + " TABLE { " + " margin: 0 auto; " + " border-collapse: inherit; " + " } " + " " + " .tabBox { " + " border-bottom: 1px solid #ccc; " + " padding-bottom: 1px; " + " height: 30px; " + " line-height: 30px; " + " color: #696969; " + " } " + " " + " .tabBox a { " + " float: left; " + " font-family: "微软雅黑"; " + " cursor: pointer; " + " padding: 0px 25px 0px; " + " font-size: 13px; " + " height: 30px; " + " line-height: 30px; " + " background: #F4F5F9; " + " border-top: 1px solid #C5D0DC; " + " border-left: 1px solid #C5D0DC; " + " border-bottom: 1px solid #C5D0DC; " + " } " + " " + " .tabBox a.current { " + " border-bottom: 0px; " + " border-top: 2px solid #7599DE; " + " font-size: 13px; " + " color: #343434; " + " background: #FFFFFF; " + " " + " } " + " " + " .tabBox a:last-child { " + " border-right: 1px solid #C5D0DC; " + " } " + " " + " .tabDetail { " + " display: none; " + " } " + " </STYLE> " + " " + " " + "<script type="text/javascript"> " + " $(function () { " + " var tabs = $("[href^='#table']"); " + " $("H1:contains('摘要')").remove(); " + " tabs.wrapAll("<p class=\"tabBox\"></p>"); " + " tabs.removeAttr("href"); " + " var tabContents = $("a[NAME]"); " + " tabContents.each(function () { " + " var tcid = $(this).attr("name"); " + " var tc = $(this).next(); " + " var tcl = $(this).prev(); " + " $(this).wrap("<div class=\"tabDetail\"></div>") " + " tc.appendTo($(this).parent()); " + " tcl.appendTo($(this).parent()); " + " }); " + " }); " + " $(function () { " + " $($('.tabBox > a')[0]).attr("class","current"); " + " $($('.tabDetail')[0]).show(); " + " $('.tabBox > a').on("click",function(){ " + " var num=$(this).index(); " + " console.log(num) " + " $('.tabBox > a').each(function(){ " + " if($(this).index()==num){ " + " $(this).attr("class","current"); " + " $('.tabDetail').hide(); " + " $($('.tabDetail')[num]).show(); " + " }else{ " + " $(this).attr("class",""); " + " } " + " }); " + " }); " + " }); " + "</script> " + "</HTML>"; RandomAccessFile raf = new RandomAccessFile(pdfFile.getAbsolutePath(), "rw"); long lastPoint = 0; //记住上一次的偏移量 String line = null; while ((line = raf.readLine()) != null) { final long ponit = raf.getFilePointer(); if (line.toUpperCase().contains("</HTML>")) { String str = line.toUpperCase().replace("</HTML>", htmlFormant); raf.seek(lastPoint); raf.write(str.getBytes("gb2312")); } lastPoint = ponit; } raf.close(); } catch (IOException e) { e.printStackTrace(); } } LOG.info("call office to pdf ,convert over. file info:" + fileEntity.toString()); } return true; } catch (OfficeException e) { e.printStackTrace(); LOG.info( "call office to pdf ,thrown error info:" + e.toString() + ", file info:" + fileEntity .toString()); return false; } } return false; }
上面有一个任意读写文件,是为了加入自定已的js 来控制excle 的展示样式。反正当时纠结了好久。
pom:
<!--open office-->
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-core</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-local</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.libreoffice</groupId>
<artifactId>juh</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>org.libreoffice</groupId>
<artifactId>jurt</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>org.libreoffice</groupId>
<artifactId>ridl</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>org.libreoffice</groupId>
<artifactId>unoil</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>org.libreoffice</groupId>
<artifactId>unoloader</artifactId>
<version>5.4.2</version>
</dependency>
代码就这么些着实有些简洁,却实现了一个看着不那么容易的功能。