快速实现通用的办公文档在线预览方案

2022-06-23 666 0

作者: 阿虎
获51CTO原创精华贴:https://ost.51cto.com/posts/14185

1. 简介

随着移动互联网的普及和快速发展,传统本地化的文档能力显得越来越不能满足需求了,由其是在协同办公及在线教学等场景上尤为突出,要实现文档的在线预览方案有很多,笔者根据经验汇总如下:

一、将文档转换为图片来预览

二、将文档转换为PDF来浏览

https://mozilla.github.io/pdf.js/
https://mozilla.github.io/pdf.js/web/viewer.html

三、将文档转换为HTML来浏览

四、搭建Office Online Server服务

https://docs.microsoft.com/zh-cn/officeonlineserver/office-online-server

五、使用第三方付费SAAS服务

https://wwo.wps.cn/docs
https://docs.qq.com/home/open
https://developer.qiniu.com/dora/10173/the-document-preview

六、开源方案

https://gitee.com/kekingcn/file-online-preview
https://gitee.com/macplus/WDA
https://github.com/ekoz/kbase-doc

2. 方案

本人也是在公司业务快速发展的基础上,为了解决用户可以通过不同的设备随时随地快速的对文档进行预览的需求场景,主导打造和封装了统一的文档转码和预览能力,主要采用方案一的方式将上传的文档预先转换成图片,再进行预览和展示;此方案主要的好处是使用简单、兼容更多环境、预览速度快,无需加载插件等,众多开源方案也是采用此方式,整体方案实现如下:
file

3. 功能一览

file

如果此刻,您也需要打造同款能力,请继续看下去,相信以下几方面内容可以快速帮到您

4. LibreOffice介绍

LibreOffice 是一款自由、免费的跨平台办公套件,它拥有所有你想要的办公软件套件的生产力功能,使其成为微软 Office 或谷歌套件的流行的开源替代品,LibreOffice 默认使用开放文档格式 (ODF),但也能很好地支持 doc/docx、xls/xlsx 等专有文档格式

https://www.libreoffice.org
https://www.libreoffice.org/discover/libreoffice-vs-openoffice/

file

4.1 LibreOffice安装

https://www.libreoffice.org/get-help/install-howto/
注:为了文档转换过程中中文字体问题,此处同时也安装了中文字体包

  • 下载程序及语言包

    wget https://download.documentfoundation.org/libreoffice/stable/7.3.4/deb/x86_64/LibreOffice_7.3.4_Linux_x86-64_deb.tar.gz &&
    wget https://download.documentfoundation.org/libreoffice/stable/7.3.4/deb/x86_64/LibreOffice_7.3.4_Linux_x86-64_deb_langpack_zh-CN.tar.gz
  • 解压文件

    mkdir LibreOffice && tar -zxvf LibreOffice_7.3.4_Linux_x86-64_deb.tar.gz -C LibreOffice && tar -zxvf LibreOffice_7.3.4_Linux_x86-64_deb_langpack_zh-CN.tar.gz  -C LibreOffice
  • 安装程序及语言包

    sudo dpkg -i LibreOffice/LibreOffice_7.3.4.*_Linux_x86-64_deb/DEBS/*.deb && sudo dpkg -i LibreOffice/LibreOffice_7.3.4.*_Linux_x86-64_deb_langpack_zh-CN/DEBS/*.deb
  • 为了程序方便调用和运行,建立相应路径软链接

    ln -s /opt/libreoffice7.3/program/soffice /usr/local/bin/libreoffice
  • 安装成功效果

    hushow@hushow-pc:~/tmp$ libreoffice --version
    LibreOffice 7.3.4.2 728fec16bd5f605073805c3c9e7c4212a0120dc5
    hushow@hushow-pc:~/tmp$ libreoffice7.3 --version
    LibreOffice 7.3.4.2 728fec16bd5f605073805c3c9e7c4212a0120dc5

    file

4.2 LibreOffice命令行转换工具

LibreOffice除了提供可视化的文件功有外,还提供了命令行文档工具,
你可以用命令行方式将文件转换为多种格式,包括 PDF、HTML、DOC、DOCX、EPUB、纯文本等。

  • 单个word转pdf格式

    libreoffice --convert-to pdf dev.docx --outdir ./target
    ├── dev.docx
    └── target
    └── dev.pdf
  • 将word转odt格式
    开放文档格式(OpenDocument Format,简称ODF)是一种规范,基于XML的文件格式

    libreoffice --convert-to odt dev.docx --outdir ./target
    ├── dev.docx
    └── target
    └── dev.odt
  • 将word转html格式

    libreoffice --convert-to "html:XHTML Writer File:UTF8" dev.docx --outdir ./target
    ├── dev.docx
    └── target
    └── dev.html
  • 批量转换

    libreoffice --convert-to pdf *.docx --outdir ./target
  • 更多高级功有自行查阅

    man libreoffice

5. 程序如何进行文档转码

在java中完成文档转码,需要依赖libreoffice、JODConverter库、PDFBox等工具,下面对具体环节进行介绍

示例下载地址:https://gitee.com/hushow/learning-demo/tree/master/spring-jodconverter-demo

5.1 文档转换成PDF

要实现文档转PDF,肯定是要用到LibreOffice工具,,但是好处就是开源的JODConverter Java库已经帮我们封装了LibreOffice相关功能,开箱即用,使用过程如下:

更多用法参考https://github.com/sbraconnier/jodconverter/blob/master/jodconverter-samples

  • 5.1.1 引入JODConverter依赖

        <dependency>
            <groupId>org.jodconverter</groupId>
            <artifactId>jodconverter-spring-boot-starter</artifactId>
            <version>4.4.2</version>
        </dependency>
    
        <dependency>
            <groupId>org.jodconverter</groupId>
            <artifactId>jodconverter-core</artifactId>
            <version>4.4.2</version>
        </dependency>
    
        <dependency>
            <groupId>org.jodconverter</groupId>
            <artifactId>jodconverter-local</artifactId>
            <version>4.4.2</version>
        </dependency>
  • 5.1.2 application.yaml配置参数

    jodconverter:
    local:
    #开关
    enabled: true
    #libreoffice安装主目录
    officeHome: /opt/libreoffice7.2
    # 最大任务进程数 100个
    max-tasks-per-process: 10
    # 开启多个LibreOffice进程 ,2003,2004
    port-numbers: 2003,2004
    #任务执行超时时间为
    taskExecutionTimeout: 33
  • 5.1.3 编码转换

    /**
    * @Description: 文档转PDF测试
    * @Author: hushow@foxmail.com
    * @Date: 2022/06/23
    **/
    @SpringBootTest
    @Slf4j
    class DocToPDFTest {
    
    @Autowired
    private DocumentConverter converter;
    
    @Test
    void docToPDFTest() throws FileNotFoundException, OfficeException {
        File srcDocFile = new File("/home/hushow/tmp/dev.docx");
        String targetExtension="pdf";
        DocumentFormat documentFormat = DefaultDocumentFormatRegistry.getFormatByExtension(targetExtension);
        File targetPdfFile = new File(srcDocFile.getParent()+File.separator+"dev.pdf");
        converter.convert(srcDocFile).to(targetPdfFile).as(documentFormat).execute();
    }
    }
  • 5.1.4 转换结果:
    file

5.2 PDF转换成图片

因为libraoffice无法将文档直接转换成完整的图片,所以需要借助其它工具将pdf再次转换成图片,本方案选用PDFBox工具,它是一个Apache开源的Java库,支持PDF文档的开发和转换。使用这个库,可以开发创建,转换和操作PDF文档的Java程序,同时支持jar命令行操作pdf,主要功能如下:

file

  • 5.2.1 添加依赖

        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.12</version>
        </dependency>
    
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox-tools</artifactId>
            <version>2.0.12</version>
        </dependency>
  • 5.2.2 代码转换

    /**
    * @Description: PDF转图片测试
    * @Author: hushow@foxmail.com
    * @Date: 2022/06/23
    **/
    @SpringBootTest
    @Slf4j
    class DemoApplicationTests {
    
    @Test
    void pdfToImageTest() {
    
        PDDocument doc = null;
        try {
            File srcPdffile = new File("/home/hushow/tmp/dev.pdf");
            doc = PDDocument.load(srcPdffile);
            String imageFileSuffix = "png";
            int pageCount = doc.getNumberOfPages();
            PDFRenderer pdfRenderer = new PDFRenderer(doc);
            String imageDir = "/home/hushow/tmp/dev";
            for (int pageIndex = 0; pageIndex < pageCount; pageIndex++) {
                String imgUrl = imageDir + File.separator + "dev" + "-" + (pageIndex+1) + imageFileSuffix;
                BufferedImage image = pdfRenderer.renderImageWithDPI(pageIndex, 105, ImageType.RGB);
                ImageIOUtil.writeImage(image, imgUrl, 105);
            }
        }catch (Exception e){
            log.error(e.getMessage(), e);
        }finally {
            if(null != doc) {
                try {
                    doc.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    }
  • 5.2.3 运行结果
    file

6 预览页面封装和定制

将文档转换成一系列的图片后,通过统一存储组件SDK,将图片存储到相应的存储服务器,为每张图片提供可仿问地址,接下来根据项目业务需求,定制相应的预览页面,最终达到文档在线预览完整方案,场景效果如下:
file

相关文章

Spring Feign大文件上传踩坑记
MinIO分布式存储方案预研
Dubbo+Grpc+Spring Boot初体验
vagrant+virtualBox快速部署集群节点
Spring Boot下grpc最佳实践
Mysql Bit类型多状态位在Java中的妙用

发布评论