documents4j使用
1. 业务背景
在许多应用场景中,将 Microsoft Word 文档(.doc 或 .docx)转换为 PDF 格式是一个常见需求。PDF 格式方便共享和查看,并且保证了文档的格式和内容一致性。为了满足这一需求,documents4j 提供了一个高效的解决方案,支持跨平台操作,包括 Windows 和 Linux 系统。
2. documents4j 简介
documents4j 是一个基于 Java 的文档转换库,支持使用 Microsoft Office API 或 LibreOffice/OpenOffice 编辑器进行文档格式转换。它能够在不同操作系统上执行文档转换任务,是一个灵活且强大的工具。
在 Windows 系统中,documents4j 通常依赖于 Microsoft Office API,而在 Linux 系统中,则需要依赖于预先安装的 LibreOffice 或 OpenOffice 进行转换。(自行查找 还没写文档)
3. Maven 依赖配置
要在项目中使用 documents4j,需要在 pom.xml 文件中添加以下依赖:
<dependency>
<groupId>com.documents4j</groupId>
<artifactId>documents4j-local</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>com.documents4j</groupId>
<artifactId>documents4j-transformer-msoffice-word</artifactId>
<version>1.0.3</version>
</dependency>
4. 核心代码实现
4.1获取操作系统类型
以下代码演示了如何根据操作系统类型选择不同的文档转换方式:
public static void convertWordToPdf(String srcPath, String destPath) throws IOException, InterruptedException {
// 获取操作系统名称
String osName = System.getProperty("os.name").toLowerCase(Locale.ROOT);
if (osName.contains("win")) {
// 如果是Windows系统,使用documents4j进行转换
convertUsingDocuments4j(srcPath, destPath);
} else if (osName.contains("nix") || osName.contains("nux") || osName.contains("mac")) {
// 如果是Linux或Mac系统,使用LibreOffice进行转换
convertUsingLibreOffice(srcPath, destPath);
} else {
throw new UnsupportedOperationException("Unsupported operating system: " + osName);
}
}
4.2 Windows 环境 word to pdf
在 Windows 环境下,可以使用 documents4j 将 Word 文档转换为 PDF 格式,代码如下:
public static void convertUsingDocuments4j(String srcPath, String destPath) throws IOException {
IConverter converter = null;
try (InputStream docxInputStream = new FileInputStream(new File(srcPath));
OutputStream outputStream = new FileOutputStream(new File(destPath))) {
// 创建LocalConverter实例
converter = LocalConverter.builder().build();
// 动态获取源文件的DocumentType
DocumentType sourceType = getDocumentTypeFromExtension(srcPath);
Future<Boolean> conversion = converter.convert(docxInputStream)
.as(sourceType) // 使用动态确定的DocumentType
.to(outputStream)
.as(DocumentType.PDF)
.schedule();
conversion.get(10, TimeUnit.SECONDS); // 等待转换完成或超时10秒
} catch (Exception e) {
e.printStackTrace();
} finally {
if (converter != null) {
converter.shutDown(); // 确保正确关闭转换器
}
}
}
其中,getDocumentTypeFromExtension 方法用于根据文件扩展名确定文档类型:
private static DocumentType getDocumentTypeFromExtension(String filePath) {
// 获取文件的扩展名并转换为小写
String extension = FilenameUtils.getExtension(filePath).toLowerCase(Locale.ROOT);
switch (extension) {
case "doc":
return DocumentType.DOC;
case "docx":
return DocumentType.DOCX;
case "rtf":
return DocumentType.RTF;
case "xls":
return DocumentType.XLS;
case "xlsx":
return DocumentType.XLSX;
case "ods":
return DocumentType.ODS;
case "csv":
return DocumentType.CSV;
case "xml":
return DocumentType.XML;
case "mhtml":
return DocumentType.MHTML;
case "txt":
return DocumentType.TEXT;
case "pdf":
return DocumentType.PDF;
case "pdfa":
return DocumentType.PDFA;
default:
throw new IllegalArgumentException("Unsupported file type: " + extension);
}
}
4.3 Linux 环境 word to pdf
在 Linux 环境中,使用 LibreOffice 进行文档转换。以下是转换的代码示例:
public static void convertUsingLibreOffice(String srcPath, String destPath) throws IOException, InterruptedException {
// 使用libreoffice7.4命令(无需完整路径)
String[] command = {
"libreoffice7.4", // 使用配置后的命令
"--headless",
"--invisible",
"--convert-to", "pdf",
srcPath,
"--outdir", new File(destPath).getParent()
};
ProcessBuilder processBuilder = new ProcessBuilder(command);
// 重定向错误流到标准输出流
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
// 读取并打印命令的输出
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new IOException("Conversion failed with exit code " + exitCode);
}
}
5. 常见问题及解决方案
问题1: Windows中书签未被正确识别
问题原因:
- 文档处理差异: documents4j和LibreOffice对Word文档处理可能不同,可能无法准确处理书签。
- 书签处理问题: documents4j可能不完全支持书签。
解决方案:
- 检查文档格式: 确保书签格式标准,尝试将文档保存为.docx格式。
- 使用其他库: 尝试Apache POI或Aspose.Words处理书签。
问题2:转换时间较长,可能需要调整超时时间
问题原因:
- 文档复杂度: 文档较大或复杂,导致转换时间长。
- 系统性能: 受限于系统的CPU和内存资源。
解决方案:
- 检查文档格式:将Future.get()中的超时时间从10秒增加到30秒或更长(也可以根据file.size()动态调整)。
- 使用其他库: 精简文档内容,删除不必要的元素,压缩图片。
问题3:Linux中书签正常识别但字体有差异
问题原因:
- 字体缺失: Linux系统中缺少字体库,导致字体显示不一致。
- 字体渲染差异: LibreOffice和其他工具在字体渲染方面可能有差异。
解决方案:
- 安装字体库: 自行查找 还没写
- 使用KKFileView字体库: 在线使用链接:https://file.kkview.cn/ 字体库下载链接:http://kkfileview.keking.cn/fonts.zip
KKFileView 是一个基于 LibreOffice 的文档在线预览工具。它利用 LibreOffice 的转换能力来将多种文档格式(如 Word、Excel、PowerPoint 等)转换为 PDF 或 HTML 格式,以便在浏览器中进行预览。
KKFileView 字体和 LibreOffice 的关系:
字体渲染: KKFileView 使用 LibreOffice 进行文档转换和渲染,这意味着文档中的字体显示取决于 LibreOffice 的字体库和渲染能力。
字体依赖: 如果 Linux 系统中缺少某些字体,LibreOffice 在渲染文档时会使用替代字体,这可能导致文档外观与原始文件有所不同。因此,KKFileView 作为基于 LibreOffice 的工具,同样会受到这种字体依赖的影响。
关键点:
安装字体: 为了确保 KKFileView 渲染的文档与原始文件一致,需要在系统中安装相应的字体库,这同样适用于 LibreOffice。
文档一致性: 通过安装正确的字体库,可以在使用 LibreOffice 或 KKFileView 时保持文档的字体和排版的一致性。
总之,KKFileView 和 LibreOffice 之间的关系在于 KKFileView 依赖 LibreOffice 的文档转换功能,而 LibreOffice 的字体库直接影响文档的渲染效果。
6. 效果图
源文件:
Windows 环境下转换的 PDF(无书签):
Linux 环境下转换的 PDF:
总结
documents4j 是一个高效的 Java 文档转换工具,适用于多种操作系统。通过结合不同平台的转换工具,如 Microsoft Office 和 LibreOffice,documents4j 能够在 Windows 和 Linux 系统中实现一致的文档转换效果。在实际应用中,根据操作系统环境选择合适的转换工具,并结合特定的优化措施,如安装字体库或调整超时时间,以确保转换效果和性能的最佳平衡。