OpenOffice在线预览附件

OpenOffice在线预览附件

Author [email protected]

Date 2018/1/20

Desc 在线预览附件功能

1.下载安装包

官方下载: http://www.openoffice.org/download/index.html

OpenOffice在线预览附件_第1张图片

2.安装OpenOffice

此处对于安装过程针对windows 和 linux两种环境分别介绍:

Windows安装
  • 双击安装包 打开运行程序 ----> 点击下一步按钮 ----> 点击浏览按钮 选择安装目录路径 -----> 会自动检测系统中的插件 如果需要会自动安装 -----> 输入使用的用户 以及选择用户权限 点击下一步按钮 -----> 勾选通常安装 点击下一步 ----> 点击完成 即安装结束

  • 接下来以命令方式启动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安装

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   
    

3.引入jodconverter-2.2.2.jar包

引入jar包的过程摸索了很久, 对于一般的java项目,直接将jar包放在lib下就可以调用; 但是恰巧我用的是maven项目, 这就需要在maven中寻找依赖, 对于我这个maven新手而言,只听过maven,见过表面的maven,并没有很深入而又熟练地掌握它的用法,尤其是碰到在pom.xml中引入依赖这种问题. 只能很羞愧地寻求小伙伴的帮助或者百度.

  • 在国内访问Maven仓库,连接速度太慢,所以我们要将中央仓库换成阿里云的中央仓库:

    http://blog.csdn.net/xiaolyuh123/article/details/74091268

  • 某些项目需要公司内部的依赖,这个时候我们就可以在项目的pom.xml中手动指定公司的仓库,比如下图,前提是公司仓库里有我们需要的依赖

    OpenOffice在线预览附件_第2张图片

  • pom.xml中引入 jar包请参考:http://blog.csdn.net/gfd54gd5f46/article/details/54973954 .

    比如我们这个在线预览的功能需要 jodconverter-2.2.2.jar , 阿里的中央仓库里并没有这个包, 我们就需要从万能的百度下载该包,然后上传到我们公司的中央仓库:https://jingyan.baidu.com/article/a948d6517b72eb0a2dcd2e2a.html , 上传之后我们的仓库里就有该依赖了 ! 如下图:

    OpenOffice在线预览附件_第3张图片

  • 仓库中的依赖已经准备好,接下来我们就在pom.xml中引入依赖:

    OpenOffice在线预览附件_第4张图片

    
    
    
    
      		
      			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

4.前台代码

在附件上传界面可以上传文件,也可以获取到文件列表的详细信息, 比如 文件在服务器上的路径,还有文件名称

OpenOffice在线预览附件_第5张图片

OpenOffice在线预览附件_第6张图片

既然文件路径都获得到了, 那我们直接将文件路径和文件名称传递到后台进行预览, 代码如下:


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,"/") 将路径中的参数全部用转义字符

5.后台代码

  • 首先我们要根据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后缀的文件

    OpenOffice在线预览附件_第7张图片

  • 将文件写到输出流中,显示在界面上,实现预览效果

详细代码如下:

/**
     * 在线预览图片
     * @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格式:

OpenOffice在线预览附件_第8张图片

.doc格式:

OpenOffice在线预览附件_第9张图片

.docx格式:

OpenOffice在线预览附件_第10张图片

.pdf格式:

OpenOffice在线预览附件_第11张图片

问题1:Uncaught SyntaxError: Invalid Unicode escape sequence

javaScrip上传文件路径字符串时, 一定要使用转义字符 ! ! ! 否则会报错

OpenOffice在线预览附件_第12张图片

问题2:unknown document format for file

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); 首先判断是不是文件路径有错误 ,如下 路径没有问题

OpenOffice在线预览附件_第13张图片

再根据错误信息追溯jodconverter源码, 发现错误信息在这里:

OpenOffice在线预览附件_第14张图片

" . "的unicode字符是46 , 所以这行代码的意思是定位 " . " 所在的位置, 而我们服务器的文件是没有后缀的,所以报错, 找到问题的原因就知道怎么解决问题了.

你可能感兴趣的:(java)