• springboot jodconverter openoffice 实现 office 文件 在线预览


    这个已是好几个月前做的,好多细节已记得不那边清楚了。今天部署到环境还遇到不少问题。总结下。

    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>

    代码就这么些着实有些简洁,却实现了一个看着不那么容易的功能。
  • 相关阅读:
    从零开始写STL-容器-双端队列
    JVM 总结
    从零开始写STL-容器-list
    从零开始写STL—容器—vector
    Web 后端编程的几个关键点(总结中...)
    Java Web 总结
    Spring实战读书笔记
    MSDN 同步部分 个人笔记
    洛谷 P3391【模板】文艺平衡树(Splay)
    洛谷 P1503 鬼子进村
  • 原文地址:https://www.cnblogs.com/kunsyliu/p/11246168.html
Copyright © 2020-2023  润新知