项目中需要将 Office 文档上传并实现在线预览,用到了 LibreOffice 将 Office 文档转换为 PDF 文档,然后再用 pdfbox 将 PDF 转为图片。
本文介绍借助 LibreOffice 将 Office 文当转换成 PDF 文档。
本文同样适用于 OpenOffice,以下仅以 LibreOffice 为例。
前言为了实现 Office 文档上传并实现在线预览功能,我试了 POI 和收费库 aspose,均不理想。
但是将 PDF 转换为图片有成熟的方案,于是,问题变成了:如何将 Office 文档转换成 PDF。
LibreOffice 可将 Office 文当转换成 PDF文件,并且效果非常棒,和通过微软的 Office 直接另存为 PDF 文件的效果几乎一样。针对在线预览的需求,效果是最好的,也许是最好的解决方案。
不过,前提是需要在服务器上安装 LibreOffice,为了测试,开发环境也需要安装,不过,好的是 LibreOffice 跨平台。 尝试通过 LibreOffice 将 Office 文档直接转换成图片,可惜只得到第一页的内容,查看帮助,没有找到直接转换为图片的方法。
Java 利用 LibreOffice 将 Office 文档转换成 PDF
有两种转换方式,各有优劣,请自行选择。
异步转换
通过调用操作系统命令的方式实现,这个转换是异步的,根据文件的大小需要的时间不确定,如果在上传之后就要立即预览,需要用同步方式。 - 优点:实现方式简单,不需要额外配置信息,不需要添加第三方依赖库(当然 LibreOffice 是必须要安装的)。 - 缺点:发送指令之后,转换是否成功,是否有异常,无法获知,也就是说,转换是否成功,是不确定的。当然,通过严格的测试,一般还是可以保证转换的可靠性的。
同步转换
用到了 JodConverter:https://github.com/sbraconnier/jodconverter - 优点:转换是同步的,转换成功与否是确定的。 - 缺点:代码运行期需要启动 LibreOffice 服务,需要占用操作系统资源,相对于异步转换方式,需要依赖第三方库,需要额外配置信息。
完整代码
添加依赖(仅同步方式需要)
org.jodconverter
jodconverter-local
4.2.4
在 resources 目录添加 libre.properties 文件(仅同步方式需要)
内容如下:
# LibreOffice主目录
libreOfficeHome=C:/dev/LibreOffice6.4
# 开启多个LibreOffice进程,每个端口对应一个进程
# portNumbers=2002,2003
portNumbers=2002
# 任务执行超时为5分钟
taskExecutionTimeoutMinutes=5
# 任务队列超时为1小时
taskQueueTimeoutHours=1
转换类 LibreOfficeUtil
package com.example.demo;
import com.example.factory.OfficeManagerInstance;
import org.jodconverter.JodConverter;
import java.io.File;
public class LibreOfficeUtil {
/*** 利用 JodConverter 将 Offfice 文档转换为 PDF(要依赖 LibreOffice),该转换为同步转换,返回时就已经转换完成*/
public static boolean convertOffice2PDFSyncIsSuccess(File sourceFile, File targetFile) {
try {
OfficeManagerInstance.start();
JodConverter.convert(sourceFile).to(targetFile).execute();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/*** 利用 LibreOffice 将 Office 文档转换成 PDF,该转换是异步的,返回时,转换可能还在进行中,转换是否有异常也未可知* @param filePath 目标文件地址* @param targetFilePath 输出文件夹* @return 子线程执行完毕的返回值*/
public static int convertOffice2PDFAsync(String filePath, String fileName, String targetFilePath) throws Exception {
String command;
int exitStatus;
String osName = System.getProperty("os.name");