事件背景
由于项目需要,最新开始研究起word转pdf了,本以为应该是一件很简单的事情,网络上应该已经有很成熟的解决方案了,毕竟在电脑上使用wps或office操作只需要另存为pdf即可,结果一顿百度,发现目前开源的方案还真没有几个能完美的解决这个问题。
实现方案
目前大家有使用的方案大概有这么几种:
- aspose-words:https://products.aspose.com/words/
- spire.doc:https://www.e-iceblue.com
- documents4j:documents4j - A document format converter for Java
- OpenOffice:Apache OpenOffice - Official Site - The Free and Open Productivity Suite
- docx4j:docx4j
- POI:Apache POI - the Java API for Microsoft Documents
aspose-words和spire.doc都是商业软件,需要花钱购买,如果是大公司,并且对生成的pdf格式保真有要求,那使用这两款收费软件无疑是最好的选择。
documents4j这种方式只适合在window上运行,对于部署在Linux服务器上的应用来说很不友好。
OpenOffice需要在服务器安装OpenOffice软件,不是很方便。
docx4j和poi这两种都是开源的,都不挑操作系统,在window和Linux上都能进行转换,但相比较poi比docx4j转换速度和保真方面都要好。
各组件的具体代码实现
poi
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.poi.xwpf.converter.pdf-gae</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.17</version>
</dependency>
@Test
public void wordToPdfTest4() throws IOException {
XWPFDocument document;
InputStream doc = Files.newInputStream(Paths.get("D:\\home\\test2.docx"));
document = new XWPFDocument(doc);
PdfOptions options = PdfOptions.create();
OutputStream out = Files.newOutputStream(Paths.get("D:\\home\\word模板转pdf4-2.pdf"));
PdfConverter.getInstance().convert(document, out, options);
doc.close();
out.close();
}
documents4j
切记,这种方式在Linux服务器不可用,所以除非你是window服务器,不然就不要使用该方案,别问我怎么知道,问就是我试过了(流泪)。
<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>
@Test
public void wordToPdfTest1() throws IOException {
InputStream docxInputStream = null;
OutputStream outputStream = null;
try {
// 原word地址
docxInputStream = Files.newInputStream(Paths.get("D:\\home\\test3.doc"));
// 转换后pdf生成地址
outputStream = Files.newOutputStream(Paths.get("D:\\home\\word模板转pdf1.pdf"));
IConverter converter = LocalConverter.builder().build();
converter.convert(docxInputStream)
.as(DocumentType.DOC)
.to(outputStream)
.as(DocumentType.PDF).execute();
// 关闭
converter.shutDown();
// 关闭
outputStream.close();
// 关闭
docxInputStream.close();
} catch (Exception e) {
System.out.println("[documents4J] word转pdf失败:" + e.toString());
} finally {
if (outputStream != null) {
outputStream.close();
}
if (docxInputStream != null) {
docxInputStream.close();
}
}
}
spire.doc
这里我测试时,一开始是从网上下载的jar包,本地引入的,因为一直提示找不到包,后来发现它没有发布到maven中心仓库,而是在自己仓库,毕竟它是收费的嘛。所以如果要使用maven下载需要添加maven仓库地址:
<repositories>
<repository>
<id>e-iceblue</id>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc.free</artifactId>
<version>5.2.0</version>
<!-- <systemPath>D:/workspace/java/java-base/lib/spire.doc.free-5.2.0.jar</systemPath>-->
</dependency>
@Test
public void wordToPdfTest2() throws IOException {
// 参考:https:
//www.cnblogs.com/Carina-baby/p/16665310.html
//实例化Document类的对象
Document doc = new Document();
//加载Word
doc.loadFromFile("D:\\home\\test3.docx");
//保存为PDF格式
doc.saveToFile("D:\\home\\word模板转pdf2-2.pdf", FileFormat.PDF);
}
由于本人目前需要转换的word比较简单,使用POI的方案也可以满足需求,所以目前我采用的是POI的方案。