Java通过documents4j和LibreOffice把word转为pdf

word转pdf的相关第三方jar说明

  • docx4j
    免费开源、稍微复杂点的word,样式完全乱了,且xalan升级为2.7.3后会报错。
  • poi
    免费开源、官方文档少、学习成本大、使用复杂、生成的样式也有问题。
  • aspire.doc
    样式保留很好、使用方便。
    未付费时,第一行会有红色水印且超过500个段落(大概25页)会被截取。
    网上没有破解版。
  • aspose.words
    样式保留很好、使用方便。
    网上有破解版。
  • documents4j
    样式保留很好、使用方便。
    底层直接调用微软的office所以,完美保留样式

Linux系统安装LibreOffice

在线安装

CentOS:使用以下命令安装

1
sudo yum install libreoffice

Ubuntu:使用以下命令安装

1
sudo apt-get install libreoffice

执行命令需要root权限:sudo -i、su

离线安装

在linux下离线安装libreoffice

word转pdf验证

查看版本:

1
libreoffice --version

启动服务:

1
nohup libreoffice --headless --accept="socket,host=127.0.0.1,port=8100;urp;" --nofirststartwizard &

word转pdf验证:

1
2
// 安装完后进入/usr/bin 或者 usr/local/bin目录下执行。 outdir输出是一个文件夹
libreoffice --headless --invisible --convert-to pdf /file/word/test.docx --outdir /file/word/test

也可以安装Apache OpenOffice,二者基本差不多,更推荐LibreOffice
LibreOffice vs OpenOffice:哪个免费办公套件更适合你?

Java工具类代码

maven依赖:

1
2
3
4
5
6
7
8
9
10
11
<!--word转pdf-->
<dependency>
<groupId>com.documents4j</groupId>
<artifactId>documents4j-local</artifactId>
<version>${documents4j.version}</version>
</dependency>
<dependency>
<groupId>com.documents4j</groupId>
<artifactId>documents4j-transformer-msoffice-word</artifactId>
<version>${documents4j.version}</version>
</dependency>

java代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package com.chinamobile.cmss.services.main.util;
import com.documents4j.api.DocumentType;
import com.documents4j.api.IConverter;
import com.documents4j.job.LocalConverter;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
* Documents4j工具类
*
* @author liquanhong
* @createTime 2023/12/05
*/
@Slf4j
public class Documents4jUtil {

// windows 生成目录
private static String winDirUrl = "D:\\temp\\file\\pdf\\";

/**
* word转pdf
*
* @param file word源文件
*/
public static void convertWordToPdf(File file) {
String os = System.getProperty("os.name").toLowerCase();
log.info("convertWordToPdf 当前操作系统:{}", os);
if (os.contains("win")) {
// Windows操作系统
windowsWordToPdf(file);
} else if (os.contains("nix") || os.contains("nux") || os.contains("mac")) {
// Unix/Linux/Mac操作系统
linuxWordToPdf(file);
} else {
// 未知操作系统
throw new RuntimeException("不支持当前操作系统转换文档。");
}
}

/**
* 通过documents4j 实现word转pdf -- Windows 环境 需要有 Microsoft Office 服务
*
* @param file 源文件
*/
public static void windowsWordToPdf(File file) {
File outputFile = new File(winDirUrl + file.getName().replaceAll("\\.(docx?|\\w+)$", "") + ".pdf");
try(InputStream docxInputStream = new FileInputStream(file);
OutputStream outputStream = new FileOutputStream(outputFile)){
IConverter converter = LocalConverter.builder().build();
converter.convert(docxInputStream)
.as(DocumentType.DOCX)
.to(outputStream)
.as(DocumentType.PDF).execute();
} catch (Exception e) {
log.error("winWordToPdf windows环境word转换为pdf时出现异常:", e);
}
}

/**
* 通过libreoffice 实现word转pdf -- linux 环境 需要有 libreoffice 服务
*
* @param file 源文件
*/
public static void linuxWordToPdf(File file) {
// 获取文件的绝对路径和目标路径
String absolutePath = file.getAbsolutePath();
String parentPath = file.getParent();

// 构建LibreOffice的命令行工具命令
String command = "libreoffice --headless --invisible --convert-to pdf " + absolutePath + " --outdir " + parentPath;
// 执行转换命令
try {
executeLinuxCmd(command);
} catch (Exception e) {
log.error("linuxWordToPdf linux环境word转换为pdf时出现异常:", e);
}
}

/**
* 执行命令行
*
* @param cmd 命令行
* @return
* @throws IOException
*/
private static boolean executeLinuxCmd(String cmd) throws IOException {
Process process = Runtime.getRuntime().exec(cmd);
try {
process.waitFor();
} catch (InterruptedException e) {
log.error("executeLinuxCmd 执行Linux命令异常:", e);
Thread.currentThread().interrupt();
return false;
}
return true;
}
}

LibreOffice不支持多线程文件转换

问题现象: 开两个窗口,执行相同的命令,命令行会卡住无反应。
在这里插入图片描述
Linux安装的版本是5.3.6.1,在windows中下载了最新版本7.6.4问题依然存在,说明和版本没关系。

参考了博客,并没有解决😭 。

后来翻到这篇博客:
使用docker来实现LibreOffice并发转换docx文件为pdf
在这里插入图片描述

结论: LibreOffice不支持多线程文件转换

其他

若命令行不指定,输出目录,LibreOffice默认输出到当前目录。
windows当前目录是,soffice.exe同级目录,如下所示:
在这里插入图片描述
linux当前目录是,输入目录的同级目录

参考链接参考链接参考链接