SpringBoot-文件在线预览解决方案-基于OpenOffice及jacob
项目中有一个需求:实现文件(主要是Office文件)的在线预览,根据前端需求,Office文件需要转换成pdf或者html方可在浏览器中打开预览,那么后端需要将文件转为pdf/格式返回地址给前端。目前,了解到的解决方案大概有两种,一种是基于Apache组织下的开源项目:OpenOffice,一种是使用jacob桥接方案。两种方案均可实现需求,但是在使用过程中遇到些许波折与坑,写在这里,与大家共勉。
方案一、OpenOffice
OpenOffice.org 是一套跨平台的办公室软件套件,能在Windows、Linux、MacOS X (X11)和 Solaris 等操作系统上执行。它与各个主要的办公室软件套件兼容。OpenOffice.org 是自由软件,任何人都可以免费下载、使用及推广它(来自 :百度百科)。
因为他是开源的,所以提供了可供java等开发语言开发的API,在此基础上,我们可以使用它来完成一些功能的转换、开发。
开发流程:
(1)安装OpenOffice
因为用到其功能,因此首先需要安装它,下载地址:https://cwiki.apache.org/confluence/display/OOOUSERS/AOO+4.1.6+Release+Notes
安装过程简单,直接下一步即可。
(2)SpringBoot集成Open Office
首先引入jar包:如下是必须的
因为有些jar包,maven仓库找不到,所以我把它放在了项目中,然后在pom文件中进行了引用
这里需要注意的是,引入jar包后,还需要在intelliJ Idea中设置project Structer引入。
(3)工具类编写
这里支持的是所有的Office文件以及txt文件,包括03版和07版均兼容。
核心代码:
/**
* 转换文件成pdf
*
* @param :
* @throws IOException
*/
public static void fileTopdfbak(File docInputFile, String toFilePath, String type) {
String timesuffix = UUID.randomUUID().toString();
String pdfFileName = null;
if("doc".equals(type)||"docx".equals(type)){
pdfFileName = timesuffix.concat(".pdf");
}else if("xls".equals(type)||"xlsx".equals(type)){
pdfFileName = timesuffix.concat(".pdf");
}else if("ppt".equals(type) || "pptx".equals(type)){
pdfFileName = timesuffix.concat(".pdf");
}else if("txt".equals(type)){
pdfFileName = timesuffix.concat(".pdf");
}else{
return ;
} String realPath=toFilePath+pdfFileName;
File pdfOutputFile = new File(realPath);
if (pdfOutputFile.exists()){
pdfOutputFile.delete();
}
String contextpath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort();
String url = contextpath +EnumUtil.CONVERT_PDF_PATH.getCode()+pdfFileName;
System.out.println("文件服务器路径:"+url);
pdfOutputFile.createNewFile();
// docInputFile.createNewFile();
OpenOfficeConnection connection = new SocketOpenOfficeConnection("127.0.0.1",8100);
System.out.println("connection:"+connection);
connection.connect();
// convert
DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection);
if(null!=docInputFile){
converter.convert(docInputFile, pdfOutputFile);
}
connection.disconnect();
// 转换完之后删除word文件
// docInputFile.delete();
}
这里需要注意的是:在使用之前需要先启动安装的Open Office服务,windows启动命令:
在安装该软件的地方进入
openOffice4/program 目录,然后cmd执行:
soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard 经过测试,该方法可用,
但是,项目中有个需求,大文件(超过2G)也需要在线预览,于是,试了下800兆的文件,测试过程中,出现了问题,800兆的文件出现了转换失败的情况,而且观察内存使用情况,发现内存使用较高,运行慢,出错后内存不会释放,报错信息:
意思大概是内存分配错误,运行OpenOffice的可视化工具,直接用这个软件好像800M的ppt也打不开,后来查资料得知,通过设置可以增加内存,但是尝试了几次,发现可设置的内存最大到256M
通过网上查资料,发现根本没有解决方法,因此该方案不得不放弃,如果大家有什么好的解决方案,欢迎留言讨论,不胜感激!
方案二、使用jacob
首先,我们需要知道什么是jacob,官方文档中有一句话:JACOB is a JAVA-COM Bridge that allows you to call COM Automation components from Java. It uses JNI to make native calls to the COM libraries. JACOB runs on x86 and x64 environments supporting 32 bit and 64 bit JVMs,翻译过了就是:Jacob是一个Java-COM桥,允许您调用COM自动化组件。不难理解,该方案提供了java和COM(ComponentObjectModel,组件对象模型)之间的一个桥梁,个人理解类似于数据库提供的驱动。
该方案的实现过程就是通过java来调用window中的Office来达到文件格式转换的目的,类似于我们打开一个文档,选择另存为其他格式的过程。因为在Windows操作平台下,众多以COM形式提供的组件模块,如DirectX多媒体软件包、OLEDB/ADO数据库组件系统等,极大地丰富了操作系统的功能。由于COM机制允许任意两组件之间相互通信而不必关心是在何种计算机上的何种操作系统下运行,也不用关心组件是使用何种语言编制的,这使COM技术拥有了强大的生命力。而我们需要的是Office的组件,因此,需要jacob来建立windows和Java之间的桥梁。
开发过程:
(1)下载jacob.jar及相关dll文件
因为在maven仓库中有该jar包,直接引入,也可直接下载:http://www.java2s.com/Code/Jar/j/Downloadjacob1143jar.htm
另外,还需要jacob-1.14.3-x64.dll(系统64位),jacob-1.14.3-x86.dll(系统32位),可以百度自行下载,这里需要注意的是版本一定要和jar包的版本保持一致。将下载好的文件拷贝一下两个目录:
C:\Windows\System32(64位),D:\Program Files\Java\jre1.8.0_131\bin jre的安装目录,注意不是jdk里面的jre,网上有说将拷贝至jdk下面的jre/bin下的,估计是环境不一样,我试过会报错。
(2)核心代码
/**
*
* @Title: ppt2PDF
* @Description: 转换ppt为office
* @param @param inputFile
* @param @param pdfFile
* @param @return 设定文件
* @return boolean 返回类型
* @throws
*/
public static boolean ppt2PDF(String inputFile,String pdfFile){
try{
System.out.println("PowerPoint.Application............");
ActiveXComponent app = new ActiveXComponent("PowerPoint.Application");
//app.setProperty("Visible", msofalse);
Dispatch ppts = app.getProperty("Presentations").toDispatch();
Dispatch ppt = Dispatch.call(ppts,
"Open",
inputFile,
true,//ReadOnly
true,//Untitled指定文件是否有标题
false//WithWindow指定文件是否可见
).toDispatch(); Dispatch.call(ppt,
"SaveAs",
pdfFile,
ppSaveAsPDF
);
Dispatch.call(ppt, "Close");
app.invoke("Quit");
return true;
}catch(Exception e){
return false;
}
} /**
*
* @Title: word2PDF
* @Description: 转换word文档为pdf
* @param @param inputFile
* @param @param pdfFile
* @param @return 设定文件
* @return boolean 返回类型
* @throws
*/
public static boolean word2PDF(String inputFile,String pdfFile){
try{
//打开word应用程序
ActiveXComponent app = new ActiveXComponent("Word.Application");
//设置word不可见
app.setProperty("Visible", false);
//获得word中所有打开的文档,返回Documents对象
Dispatch docs = app.getProperty("Documents").toDispatch();
//调用Documents对象中Open方法打开文档,并返回打开的文档对象Document
Dispatch doc = Dispatch.call(docs,
"Open",
inputFile,
false,
true
).toDispatch();
//调用Document对象的SaveAs方法,将文档保存为pdf格式
/*
Dispatch.call(doc,
"SaveAs",
pdfFile,
wdFormatPDF //word保存为pdf格式宏,值为17
);
*/
Dispatch.call(doc,
"ExportAsFixedFormat",
pdfFile,
wdFormatPDF //word保存为pdf格式宏,值为17
);
//关闭文档
Dispatch.call(doc, "Close",false);
//关闭word应用程序
app.invoke("Quit", 0);
return true;
}catch(Exception e){
return false;
}
} /**
*
* @Title: excel2PDF
* @Description: 转换excel为PDF
* @param @param inputFile
* @param @param pdfFile
* @param @return 设定文件
* @return boolean 返回类型
* @throws
*/
public static boolean excel2PDF(String inputFile,String pdfFile){
try{
ActiveXComponent app = new ActiveXComponent("Excel.Application");
app.setProperty("Visible", false);
Dispatch excels = app.getProperty("Workbooks").toDispatch();
Dispatch excel = Dispatch.call(excels,
"Open",
inputFile,
false,
true
).toDispatch();
Dispatch.call(excel,
"ExportAsFixedFormat",
xlTypePDF,
pdfFile
);
Dispatch.call(excel, "Close",false);
app.invoke("Quit");
return true;
}catch(Exception e){
return false;
}
}
测试结果:直接上800M的ppt,测试结果:
经过测试,只要是微软Office能打开的文件,都可以完成转换。
(4)问题及坑
开发过程中,发现测试在本地可行,发布到服务器报错,内容如下:
java.lang.NoSuchMethodError: com.jacob.com.Dispatch.call(Lcom/jacob/com/Dispatch;Ljava/lang/String;[Ljava/lang/Object;)Lcom/jacob/com/Variant;
at com.thupdi.project.utils.OfficeToPDFUtils.ppt2PDF(OfficeToPDFUtils.java:99)
at com.thupdi.project.utils.OfficeToPDFUtils.convert2PDF(OfficeToPDFUtils.java:69)
方法找不到,应该是缺少jar包或者jar包冲突导致的。
解决方案,找到之前引用的jar包,因为之前在项目中导入过jacob.jar包,所以导致冲突。还有一种可能就是maven打包的时候没有把项目中引用的jar包(非maven引入)一并打入war/jar包,导致找不到方法。按这种方法顺利解决的问题,大家如果有这个问题,可以按这两个方法尝试解决。
SpringBoot-文件在线预览解决方案-基于OpenOffice及jacob的更多相关文章
- 基于开源方案构建统一的文件在线预览与office协同编辑平台的架构与实现历程
大家好,又见面了. 在构建业务系统的时候,经常会涉及到对附件的支持,继而又会引申出对附件在线预览.在线编辑.多人协同编辑等种种能力的诉求. 对于人力不是特别充裕.或者项目投入预期规划不是特别大的公司或 ...
- 网页中动态嵌入PDF文件/在线预览PDF内容https://www.cnblogs.com/xgyy/p/6119459.html
#网页中动态嵌入PDF文件/在线预览PDF内容# 摘要:在web开发时我们有时会需要在线预览PDF内容,在线嵌入pdf文件: 问题1:如何网页中嵌入PDF: 在网页中: 常用的几种PDF预览代码片段如 ...
- 文件在线预览doc,docx转换pdf(一)
文件在线预览doc,docx转换pdf(一) 1. 前言 文档转换是一个是一块硬骨头,但是也是必不可少的,我们正好做的知识库产品中,也面临着同样的问题,文档转换,精准的全文搜索,知识的转换率,是知识库 ...
- word文档在线预览解决方案
花了一整天在网上翻关于 “word文档在线预览解决方案” 相关的资料,感觉实现难度比较大还是用PDF来解决好了.. 下面列一下比较好的参考资料吧 参考资料 前端实现在线预览pdf.word.xls.p ...
- kkfileview v2.0 发布,文件在线预览项目方案
kkfileview文件在线预览 此项目为文件文档在线预览项目解决方案,项目使用流行的spring boot搭建,易上手和部署,部署好后可以独立提供预览服务,使用http接口访问,不需要和应用集成,具 ...
- kkFileView对接svn服务完成文件在线预览功能
1.需求: 之前在公司内部搭建了svn服务器,给部门存放文档.视频,做成了一个文档服务器来用,随着视频文件太大,每次下载太慢 需要把文件在线打开查看 2.解决: kkFileView https:// ...
- asp.net word ecxel类型文件在线预览
asp.net word ecxel类型文件在线预览 首先得引用COM: Microsoft Excel 10 Object Library Microsoft Word 10 Object Libr ...
- 使用PDF.JS实现pdf文件在线预览时,报文件被损坏的错误
首先大概说明一下问题出现的背景:我用PDF.JS实现文件在线预览,参考网上的办法,在jsp文件中使用 <iframe src="<c:url value="js/gen ...
- C# WebAPI 文件在线预览
最近在写一个移动端API接口,其中有一个需求:接口返回附件url地址让手机端调用实现文件在线预览.大体实现思路:把doc.xls等文本格式文件转换为pdf,转换后的pdf文件存放在服务器上面,方便第二 ...
随机推荐
- Jmeter学习笔记(五)——dubbo接口测试
一.什么是dubbo接口 Dubbo 接口是阿里巴巴开源的致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案,dubbo框架告别了传统的web service的服务模式,进而改用 ...
- ESLint——从零学起
介绍 ESLint最初是由Nicholas C. Zakas于2013年6月创建的开源项目.它的目标是提供一个插件化的javascript代码检测工具.因此,ESLint就是一个语法规则和代码风格的检 ...
- code first从入门到伪精通
新入职一家公司,虽然之前也用ef,但是方式不一样,之前用的db,现在用代码先行的code,基于现有公司基本项目框架都是用的code,所以一步登顶,从最实战的角度去操作code,心颤的很,废话不多说,开 ...
- springcloud 之Ribbon客户端负载均衡配置使用
pom.xml添加配置说明:这里服务注册与发现用的是Eureka,所以消费者端需要引入eureka,使用EurekaClient来调用服务 <dependency> <groupId ...
- python之约束、加密及logging模块
一.什么是约束? 在生活中的约束大概就是有什么原因,导致你不能做这件事情了,称之为约束.而在python中的约束是在当多个类中,都需要使用某些方法时,需要人为抛出异常或使用基类+异常处理来进行约束 c ...
- Java关键字—final
final—不可变的,用来说明最终属性,表明一个类不能派生出子类,或者成员方法不能被覆盖,或者成员域的值不能被改变. 修饰范围: 1.修饰类,被final关键字修饰的类无法被继承: 2.修饰方法,被f ...
- 利用random模块做一个抢红包功能
我们都知道random模块是一个生成随机数的模块,用它来做抢红包的功能很合适. 抢红包,抢到的金额是随机的,但怎么让每个人抢到的随机金额公平合理呢 比如:我想发一个100元的红包让10个人抢,我可以把 ...
- FontLab
FontLab 字体制作软件
- XAMPP启动Apache服务时启动失败
9:48:49 [Apache] Apache Service detected with wrong path 9:48:49 [Apache] Change XAMPP Apache and Co ...
- matlab(5) : 求得θ值后用模型来预测 / 计算模型的精度
求得θ值后用模型来预测 / 计算模型的精度 ex2.m部分程序 %% ============== Part 4: Predict and Accuracies ==============% Af ...