可能是国内封装 Libreoffice 最好的一个项目

本贴最后更新于 1805 天前,其中的信息可能已经时移世改

基于 libreoffice 实现的文档转换项目,无框架依赖,即插即用

项目源代码:github/workable-converter

1. 技术栈

  • LibreOffice:v6.2.3

  • jodconverter:4.2.2

  • PDFBox:2.0.12

  • cglib 动态代理 + 懒汉工厂模式 + 策略模式 + 装饰器模式

  • qtools-property 管理配置文件(application.yml、bootstrap.yml、workable-converter.yml 三种命名的配置文件任意包含一种即可)

2. 功能

  • 支持 doc、docx、html、ppt、png、pdf 等等类型的文件互相转换

  • 支持按照文件路径、字节输入输出流、Base64 等不同姿势转换

  • 不依赖第三方框架,即插即用,支持 application.yml、bootstrap.yml、workable-converter.yml 三种配置(自己项目中具体配置一个即可)

3. 使用

3.1 安装配置 LibreOffice6.2.3

CentOS 请直接参考这篇文章:CentOS7 安装 LibreOffice6.2.3

windows 跟 Mac 同样可以在上述文章中拿到下载链接

安装完成后,请记住您的 LibreOffice 的 Home 目录,后面需要用到

默认目录:

  • CentOS: /opt/libreoffice6.2/

  • Mac: /Applications/LibreOffice.app/Contents/

  • Windows: C:\Program Files\LibreOffice\

3.2 获取依赖

  • Maven
<dependency>
  <groupId>com.liumapp.workable.converter</groupId>
  <artifactId>workable-converter</artifactId>
  <version>v1.1.0</version>
</dependency>
  • Gradle
compile group: 'com.liumapp.workable.converter', name: 'workable-converter', version: 'v1.1.0'

3.3 编辑配置文件

在项目的 resources 目录下,创建一个 yml 配置文件,需要确保文件名称为 application.yml、bootstrap.yml 或 workable-converter.yml 三种命名任意一个即可

添加以下配置:

com:
  liumapp:
    workable-converter:
      libreofficePath: "/Applications/LibreOffice.app/Contents"

libreofficePath 的值为 LibreOffice:6.2.3 的安装目录

完整的配置项列表如下

参数名解释默认值
libreofficePathLibreOffice安装目录(String) 无默认值,该项必填
libreofficePortLibreOffice监听端口(int) 2002
tmpPath临时存储目录(String) "./data/"

3.4 执行转换

3.4.1 按照文件路径转换

以 doc 转 PDF 为例

WorkableConverter converter = new WorkableConverter();//实例化的同时,初始化配置项,配置项的校验通过Decorator装饰

ConvertPattern pattern = ConvertPatternManager.getInstance();
pattern.fileToFile("./data/test.doc", "./data/pdf/result1.pdf"); //test.doc为待转换文件路径,result1.pdf为转换结果存储路径
pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.DOC);
pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PDF);

converter.setConverterType(CommonConverterManager.getInstance());//策略模式,后续实现了新的转换策略后,在此处更换,图片转换将考虑使用新的策略来完成
boolean result = converter.convert(pattern.getParameter();

如果要用 html 转 PDF,将上述代码的

pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.DOC);
pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PDF);

改为

pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.HTML);
pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PDF);

其他类型的同理

3.4.2 按照输入输出流转换

以 doc 转 pdf 为例

// you can also choice not use proxy
WorkableConverter converter = new WorkableConverter();
ConvertPattern pattern = ConvertPatternManager.getInstance();
pattern.streamToStream(new FileInputStream("./data/test.doc"), new FileOutputStream("./data/pdf/result1_2.pdf"));
// attention !!! convert by stream must set prefix.
pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.DOC);
pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PDF);
converter.setConverterType(CommonConverterManager.getInstance());
boolean result = converter.convert(pattern.getParameter();

跟上例基本相同,唯一的变化是通过 pattern.streamToStream()来设置输入输出流,转换源文件数据从输入流中读取,转换结果会直接写入输出流中,

同时要切换转换格式,跟上例一样设置不同的 prefix 即可

3.4.3 按照文件 Base64 转换

仍以 doc 转 pdf 为例

WorkableConverter converter = new WorkableConverter();
ConvertPattern pattern = ConvertPatternManager.getInstance();
pattern.base64ToBase64(Base64FileTool.FileToBase64(new File("./data/test.doc")));
// attention !!! convert by base64 must set prefix.
pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.DOC);
pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PDF);
converter.setConverterType(CommonConverterManager.getInstance());
boolean result = converter.convert(pattern.getParameter();
String destBase64 = pattern.getBase64Result();

输入 base64 执行转换,首先通过 pattern.base64ToBase64()来设置转换源的 base64 值

转换结果 result 仍然是一个 boolean 类型,通过 pattern.getBase64Result 来获取转换结果的 base64 值

要切换转换格式,跟上例一样设置不同的 prefix 即可

3.5 图片处理

目前对于图片的处理,只支持将 PDF 转 PNG 图片(如果 1 份 pdf 文件有 20 页,那么将会转换为 20 张 png 图片),该功能的实现基于 PDFBox:2.0.12

3.5.1 按照文件路径处理

pattern.fileToFiles()第一个参数为待转换的 pdf 文件路径,第二个参数为转换后的图片存储路径

WorkableConverter converter = new WorkableConverter();
ConvertPattern pattern = ConvertPatternManager.getInstance();
pattern.fileToFiles("./data/test5.pdf", "./data/");
pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.PDF);
pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PNG);
converter.setConverterType(PdfBoxConverterManager.getInstance()); // pdf box converter manager only support pdf to png
assertEquals(true, converter.convert(pattern.getParameter()));
assertEquals(true, FileTool.isFileExists("./data/test5_0.png"));
assertEquals(true, FileTool.isFileExists("./data/test5_1.png"));
assertEquals(true, FileTool.isFileExists("./data/test5_2.png"));
assertEquals(true, FileTool.isFileExists("./data/test5_3.png"));

3.5.2 按照文件 Base64 处理

pattern.base64ToBase64()的参数为待转换 pdf 文件的 base64 值

转换结束后,通过 List<String> resultBase64 = pattern.getBase64Results() 获取转换后的图片 base64 值的集合

WorkableConverter converter = new WorkableConverter();
ConvertPattern pattern = ConvertPatternManager.getInstance();
pattern.base64ToBase64(Base64FileTool.FileToBase64(new File("./data/test5.pdf")));
pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.PDF);
pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PNG);
converter.setConverterType(PdfBoxConverterManager.getInstance()); // pdf box converter manager only support pdf to png
boolean result = converter.convert(pattern.getParameter());
List<String> resultBase64 = pattern.getBase64Results();
assertEquals(true, result);
assertEquals(4, resultBase64.size());

4. 待办事项

  • 已经测试通过的有 doc、docx、html 按照不同姿势转 PDF,其他类型的并没有编写测试单元,后续考虑增加

  • 目前只支持 yml 配置,后续考虑添加其他类型的配置支持(xml、properties 等)

  • 目前 Markdown 格式很流行,考虑实现 markdown 格式的字符串转 PDF(markdown -> html -> pdf)

5. 注意事项

  • 因为需要 LibreOffice 的支持,所以不建议在 Docker 等容器内运行(LibreOffice 暂无 Docker 稳定发行版的镜像)

  • 转换乱码、转换耗时过长,请检查服务器是否安装有中文字体

  • 项目启动后,在执行第一次转换任务时,因为涉及到与 LibreOffice 建立连接等操作,所以会耗时较长,第二次任务及以后稳定在 0.5 秒以内(具体时间因机器配置会有所差异)

6. 参考链接

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3168 引用 • 8207 回帖
  • LibreOffice
    3 引用 • 3 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...