Author [email protected]
Date 2018/1/20
Desc 在线预览附件功能
官方下载: http://www.openoffice.org/download/index.html
此处对于安装过程针对windows 和 linux两种环境分别介绍:
双击安装包 打开运行程序 ----> 点击下一步按钮 ----> 点击浏览按钮 选择安装目录路径 -----> 会自动检测系统中的插件 如果需要会自动安装 -----> 输入使用的用户 以及选择用户权限 点击下一步按钮 -----> 勾选通常安装 点击下一步 ----> 点击完成 即安装结束
接下来以命令方式启动OpenOffice服务
cd C:\Program Files (x86)\OpenOffice 4\program
soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard
服务打开成功之后在任务管理器可以看见soffice.bin的进程。
注意: 使用OpenOffice的时候一定要打开服务 !
比如我自己电脑晚上关机了,服务就自己关闭, 使用预览功能时候会报错:
java.net.ConnectException: connection failed: socket,host=127.0.0.1,port=8100,tcpNoDelay=1: java.net.ConnectException: Connection refused: connect at .....
linux安装教程可以参考网址:https://www.cnblogs.com/goodcheap/p/7929986.html
启动服务和windows不同的是,需要在命令末尾加 &
cd /opt/openoffice4/program
soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard &
查看服务是否成功启动
[root@vs058 program]# ps -ef|grep openoffice
root 24818 24804 19 15:08 pts/4 00:00:00 /opt/openoffice4/program/soffice.bin -headless -accept=socket,host=127.0.0.1,port=8100;urp; -nofirststartwizard
root 24824 24592 0 15:08 pts/4 00:00:00 grep openoffice
[root@vs058 program]# netstat -lnp |grep 8100
tcp 0 0 127.0.0.1:8100 0.0.0.0:* LISTEN 24818/soffice.bin
引入jar包的过程摸索了很久, 对于一般的java项目,直接将jar包放在lib下就可以调用; 但是恰巧我用的是maven项目, 这就需要在maven中寻找依赖, 对于我这个maven新手而言,只听过maven,见过表面的maven,并没有很深入而又熟练地掌握它的用法,尤其是碰到在pom.xml中引入依赖这种问题. 只能很羞愧地寻求小伙伴的帮助或者百度.
在国内访问Maven仓库,连接速度太慢,所以我们要将中央仓库换成阿里云的中央仓库:
http://blog.csdn.net/xiaolyuh123/article/details/74091268
某些项目需要公司内部的依赖,这个时候我们就可以在项目的pom.xml中手动指定公司的仓库,比如下图,前提是公司仓库里有我们需要的依赖
pom.xml中引入 jar包请参考:http://blog.csdn.net/gfd54gd5f46/article/details/54973954 .
比如我们这个在线预览的功能需要 jodconverter-2.2.2.jar , 阿里的中央仓库里并没有这个包, 我们就需要从万能的百度下载该包,然后上传到我们公司的中央仓库:https://jingyan.baidu.com/article/a948d6517b72eb0a2dcd2e2a.html , 上传之后我们的仓库里就有该依赖了 ! 如下图:
仓库中的依赖已经准备好,接下来我们就在pom.xml中引入依赖:
com.hand.hap
jodconverter
2.2.2
org.slf4j
slf4j-api
1.7.25
org.openoffice
juh
4.1.2
org.openoffice
jurt
4.1.2
org.openoffice
ridl
4.1.2
org.openoffice
unoil
4.1.2
com.thoughtworks.xstream
xstream
1.4.10
有小伙伴说很难找到jar包,我把jar包上传到了百度云盘里,大家根据项目选择不同的版本
链接:https://pan.baidu.com/s/16ujGhvEC4v1ucjkGwpCz7g
提取码:dgsm
在附件上传界面可以上传文件,也可以获取到文件列表的详细信息, 比如 文件在服务器上的路径,还有文件名称
既然文件路径都获得到了, 那我们直接将文件路径和文件名称传递到后台进行预览, 代码如下:
kendoUI-Grid:
{
field: "",
headerAttributes: {
style: "text-align: center"
},
attributes: {style: "text-align:center"},
title: '预览',
width: 50,
template: function (e) {
return ''
+ '预览'
+ ''
}
}
将参数传递到controller:
function preview(filePath , fileName) {
window.open("${base.contextPath}/sys/attach/preview?filePath="+filePath+"&fileName="+fileName);
}
注意:
"+item.basicId+"
\""+item.candidateRuleCode+"\"
用双引号将参数包围,同时使用转义符。"/"
或者 "\"
, 只用双引号将参数包围会出错:Uncaught SyntaxError: Invalid Unicode escape sequence
, 所以我们用 .replace(/\\/g,"/")
将路径中的参数全部用转义字符首先我们要根据System.getProperty("os.name")
获得服务器类别, 然后自由转换文件路径, 比如linux就是``"/",windows就是
""`
对于HAP框架来说, 文件上传到服务器时是不带后缀名的,这个时候利用jodconverter将docx文件转换为pdf文件时就会出现错误java.lang.IllegalArgumentException: unknown document format for file:
, 所以我们就要改造框架封装好的上传方法,此处不做介绍. 或者通过file.renameto(newFile)
将文件重命名为带后缀的,但是我们下载的功能就要随之修改咯 !
然后根据不同的文件扩展名设置ContentType:http://tool.oschina.net/commons
然后连接端口号8100, 这个端口号和打开OpenOffice服务的端口号是一致的, 然后通过converter.convert(docFile, pdfFile);
将文件成功转换为 .pdf后缀的文件
将文件写到输出流中,显示在界面上,实现预览效果
详细代码如下:
/**
* 在线预览图片
* @param request
* @param response
* @param filePath
* @param fileName
* @throws IOException
*/
@RequestMapping(value = "/sys/attach/preview")
public ResponseData preview(HttpServletRequest request, HttpServletResponse response, @RequestParam String filePath, @RequestParam String fileName) throws IOException {
IRequest requestContext = this.createRequestContext(request);
ResponseData responseData = new ResponseData();
response.setContentType("text/html; charset=UTF-8");
if(!"".equals(filePath)) {
/*1)根据项目所在的服务器环境,确定路径中的 / 和 \ */
String osName = System.getProperty("os.name");
if (Pattern.matches("Linux.*", osName)) {
filePath = "/" + filePath.replace("\\","/");
} else if(Pattern.matches("Windows.*", osName)) {
filePath.replace("/","\\");
}
/*2)获得文件名后缀*/
String ext = "";
if(!"".equals(fileName) && fileName.contains(".")){
ext = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()).toUpperCase();
}
/*3)根据文件类型不同进行预览*/
/*预览图片*/
if ("PNG".equals(ext) || "JPEG".equals(ext) || "JPG".equals(ext)) {
response.setContentType("image/jpeg");
}
/*预览BMP格式的文件*/
if ("BMP".equals(ext)) {
response.setContentType("image/bmp");
}
/*预览pdf*/
if ("PDF".equals(ext)) {
response.setContentType("application/pdf");
}
/*利用openOffice将office文件转换为pdf格式, 然后预览doc, docx, xls, xlsx, ppt, pptx */
if ("DOC".equals(ext) || "DOCX".equals(ext) || "XLS".equals(ext) || "XLSX".equals(ext) || "PPT".equals(ext) || "PPTX".equals(ext)) {
/*filePath在数据库中是不带文件后缀的, 由于jodConverter必须要识别后缀,所以将服务器中的文件重命名为带后缀的文件*/
File docFile = new File(filePath);
/*File docFileWithExt = new File(filePath + "." + ext.toLowerCase()); //带后缀的文件
docFile.renameTo(docFileWithExt);
*/
/*转换之后的文件名*/
File pdfFile;
if(filePath.contains(".")){
pdfFile = new File(filePath.substring(0, filePath.lastIndexOf(".")) + ".pdf");
}else{
pdfFile = new File(filePath + ".pdf");
}
/*判断即将要转换的文件是否真实存在*/
if (docFile.exists()) {
/*判断改文件是否已经被转换过,若已经转换则直接预览*/
if (!pdfFile.exists()) {
/*打开OpenOffice连接,*/
OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100);
try {
connection.connect();
DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
converter.convert(docFile, pdfFile);
connection.disconnect();
filePath = pdfFile.getPath(); //文件转换之后的路径
response.setContentType("application/pdf");
} catch (java.net.ConnectException e) {
e.printStackTrace(); //openoffice 服务未启动
throw e;
} catch (com.artofsolving.jodconverter.openoffice.connection.OpenOfficeException e) {
e.printStackTrace(); //读取转换文件失败
throw e;
} catch (Exception e) {
e.printStackTrace();
throw e;
}finally { //发生exception时, connection不会自动切断, 程序会一直挂着
try{
if(connection != null){
connection.disconnect();
connection = null;
}
}catch(Exception e){}
}
} else {
filePath = pdfFile.getPath(); //文件已经转换过
response.setContentType("application/pdf");
}
} else {
responseData.setSuccess(false);
responseData.setMessage("需要预览的文档在服务器中不存在!");
return responseData;
}
}
/*将文件写入输出流,显示在界面上,实现预览效果*/
FileInputStream fis = new FileInputStream(filePath);
OutputStream os = response.getOutputStream();
try {
int count = 0;
byte[] buffer = new byte[1024 * 1024];
while ((count = fis.read(buffer)) != -1)
os.write(buffer, 0, count);
os.flush();
responseData.setSuccess(true);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (os != null)
os.close();
if (fis != null)
fis.close();
}
}
return responseData;
}
总结,转换文件的核心代码就下边几句:
OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100);
connection.connect();
DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
converter.convert(docFile, pdfFile);
connection.disconnect();
实现效果如下:
npm jpg格式:
.doc格式:
.docx格式:
.pdf格式:
javaScrip上传文件路径字符串时, 一定要使用转义字符 ! ! ! 否则会报错
openOffice 将.docx文件转换为.pdf时出错
2018-01-18 20:10:23.312 DEBUG [10001] [1804f437cb4f400f9f22b4b0816c02c9] com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection - connecting
2018-01-18 20:10:23.860 INFO [10001] [1804f437cb4f400f9f22b4b0816c02c9] com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection - connected
java.lang.IllegalArgumentException: unknown document format for file: D:\usr\pictures\hap\img\787dc887-9dba-4c7b-969a-c5b497268f9f
debug 代码: converter.convert(docFile, pdfFile); 首先判断是不是文件路径有错误 ,如下 路径没有问题
再根据错误信息追溯jodconverter源码, 发现错误信息在这里:
" . "的unicode字符是46 , 所以这行代码的意思是定位 " . " 所在的位置, 而我们服务器的文件是没有后缀的,所以报错, 找到问题的原因就知道怎么解决问题了.