Java开发中Word转PDF文件5种方案横向评测
前段时间接了个项目,需要各种处理Word模板、转PDF、签章等等,非常头疼,其中光是一个word转PDF就折磨我好久,实现转换很简单,但是效果总是达不到满意,于是我把市面上能找到的word转pdf方法都试了个遍。现在把这些方案来做个横向对比,希望对大家能有帮助。
对比的时候我选择了两个指标来进行对比。
关于Word转PDF网上能找到的方案大概有六七种,我选了其中的5种,分别是:
aspose-words、docx4j、openoffice、poi、spire.doc
下面先来简单介绍一下这五种方案
Aspose公司旗下的最全的一套office文档管理方案,公司设在澳大利亚。
公司差不多是专做各种文件格式处理插件的,产品系列挺多,有兴趣可以到官网上看看:
https://www.aspose.com/
许可 | ||
---|---|---|
Developer Small Business - 1 Developer and 1 Deployment Location | 开发人员小型企业- 1个开发人员和1个部署位置 | 29,291 元 |
Developer OEM - 1 Developer and Unlimited Deployment Locations | 开发人员OEM - 1开发人员和无限部署地点 | 87,874 元 |
Site Small Business - Up to 10 Developers and up to 10 Deployment Locations | 站点小型企业-多达10个开发人员和多达10个部署地点 | 146,456元 |
Site OEM - Up to 10 Developers and Unlimited Deployment Locations | 站点OEM -多达10个开发人员和无限部署地点 | 410,077 元 |
技术支持服务 | ||
Developer Small Business 1 Year Developer Support License - up to 3 incidents per year | 开发人员小型企业1年开发人员支持许可证-每年最多3起事故 | 2,923 元 |
Aspose Business Support 商业服务 | ||
Developer Small Business 1 Year Business Support License - up to 6 incidents per year | 开发商小型企业1年业务支持许可证-每年最多6起事故 | 4,387 元 |
Developer OEM 1 Year Business Support License - up to 6 incidents per year | 开发人员OEM 1年业务支持许可证-每年最多发生6起事故 | 13,162 元 |
企业支持 | ||
Site Small Business 1 Year Enterprise Support License - up to 6 incidents per year | 网站小型企业1年企业支持许可证-每年最多6起事故 | 29,262 元 |
Site OEM 1 Year Enterprise Support License - up to 6 incidents per year | 站点OEM 1年企业支持许可证-每年最多发生6起事故 | 87,786 元 |
不需要依赖任何组件,不依赖操作系统。
大名鼎鼎的apache的开源组件,应用非常广泛,我想主要原因可能是开源吧。
官网:https://poi.apache.org/
组件拆分较细,引用一些类库,但都问题不大,不依赖操作系统。
Apache旗下又一开源组件,前身是1998年一家德国公司StarDivision所研发出来的一个办公室软件,称之为StarOffice。1999年8月被sun公司收购。2010年团队成员分家,分出来的一批成立了新团队做一个LibreOffice。2011年6月Oracle将其捐赠给Apache基金会。
官网:https://www.openoffice.org/
OpenOffice本身就是一套Office软件,该方案需要使用jodconverter组件配合OpenOffice完成转换,当然也可以使用LibreOffice进行转换,这次并没有测试这个方案
jodconverter:https://sourceforge.net/projects/jodconverter/files/
搜到的时候刚刚打开官网猛一看以为是国外的公司,没想到一切到中文版网页才发现是成都冰蓝科技有限公司出品的,真正的国产。刚刚查到官网的时候是非常期待他的表现的。
官网:https://www.e-iceblue.com/ https://www.e-iceblue.cn/
不需要依赖任何组件,不依赖操作系统。
只截图了spire.doc组件的价格,其它还有很多组件。用公司名和邮箱可以申请一个月的试用license。
澳大利亚一公司赞助的开源组件,一查资料才知道作者是这家公司的CEO。刚刚打开官网的时候就一个感觉,官网做的太烂,不太相信这组件能有什么好的表现。下面的图就是官网截图,相信你会有一样的感觉。
有一个开源版,还有一个Docx4j Enterprise Edition。没有仔细研究,只测试了开源版。
官网:https://www.docx4java.org/
不依赖其它组件,不依赖操作系统
除了以上几种方案以外,还查到有其它几乎方案,比如IText、document4j等。像IText是依赖于poi的,document4j是依赖于office软件的,所以不测试了。
测试的word文档我选取的是我项目中用到的一个文档,正好是遇到比较容易出现跳页的情况。拿来做横向测试非常合适,先来欣赏一下word文档吧。
文档中标题、表格、页眉页脚、图片、文本框几乎都用到了,准备就绪,开始测试。。
<dependency>
<groupId>com.asposegroupId>
<artifactId>aspose-wordsartifactId>
<version>22.11version>
<classifier>jdk17classifier>
dependency>
package com.hawkon.aspose;
import com.aspose.words.*;
public class WordToPdfTest_Aspose {
public static void wordToPdf(String wordFile, String pdfFile) throws Exception {
Document wordDoc = new Document(wordFile);
PdfSaveOptions pso = new PdfSaveOptions();
wordDoc.save(pdfFile, pso);
}
}
aspose这个组件是商用的,正常的写上如上所示,但是试用版导出的PDF文件是阉割版的,没法进行测试对比,所以我用了网上留传(po jie)的版本,有需要的朋友可以关注我的公众号(姚Sir面试间),回复aspose就可以得到。
本地jar包导入方法
<dependency>
<groupId>com.asposegroupId>
<artifactId>aspose-wordsartifactId>
<version>19.5.0version>
<scope>systemscope>
<systemPath>D:/Code/PdfTest/lib/aspose-words-19.5jdk.jarsystemPath>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-simpleartifactId>
<version>1.7.21version>
dependency>
<dependency>
<groupId>org.docx4jgroupId>
<artifactId>docx4j-JAXB-InternalartifactId>
<version>8.2.4version>
dependency>
<dependency>
<groupId>org.docx4jgroupId>
<artifactId>docx4j-export-foartifactId>
<version>8.2.4version>
dependency>
package com.hawkon.docx4j;
import org.docx4j.Docx4J;
import org.docx4j.fonts.IdentityPlusMapper;
import org.docx4j.fonts.Mapper;
import org.docx4j.fonts.PhysicalFonts;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileOutputStream;
public class WordToPdfTest_Docx4j {
public static void wordToPdf(String docFile,String pdfFile) throws Exception {
final Logger logger = LoggerFactory.getLogger(Docx4J.class);
WordprocessingMLPackage pkg = Docx4J.load(new File(docFile));
Mapper fontMapper = new IdentityPlusMapper();
fontMapper.put("隶书", PhysicalFonts.get("LiSu"));
fontMapper.put("宋体", PhysicalFonts.get("SimSun"));
fontMapper.put("微软雅黑", PhysicalFonts.get("Microsoft Yahei"));
fontMapper.put("黑体", PhysicalFonts.get("SimHei"));
fontMapper.put("楷体", PhysicalFonts.get("KaiTi"));
fontMapper.put("新宋体", PhysicalFonts.get("NSimSun"));
fontMapper.put("华文行楷", PhysicalFonts.get("STXingkai"));
fontMapper.put("华文仿宋", PhysicalFonts.get("STFangsong"));
fontMapper.put("仿宋", PhysicalFonts.get("FangSong"));
fontMapper.put("幼圆", PhysicalFonts.get("YouYuan"));
fontMapper.put("华文宋体", PhysicalFonts.get("STSong"));
fontMapper.put("华文中宋", PhysicalFonts.get("STZhongsong"));
fontMapper.put("等线", PhysicalFonts.get("SimSun"));
fontMapper.put("等线 Light", PhysicalFonts.get("SimSun"));
fontMapper.put("华文琥珀", PhysicalFonts.get("STHupo"));
fontMapper.put("华文隶书", PhysicalFonts.get("STLiti"));
fontMapper.put("华文新魏", PhysicalFonts.get("STXinwei"));
fontMapper.put("华文彩云", PhysicalFonts.get("STCaiyun"));
fontMapper.put("方正姚体", PhysicalFonts.get("FZYaoti"));
fontMapper.put("方正舒体", PhysicalFonts.get("FZShuTi"));
fontMapper.put("华文细黑", PhysicalFonts.get("STXihei"));
fontMapper.put("宋体扩展", PhysicalFonts.get("simsun-extB"));
fontMapper.put("仿宋_GB2312", PhysicalFonts.get("FangSong_GB2312"));
pkg.setFontMapper(fontMapper);
Docx4J.toPDF(pkg, new FileOutputStream(pdfFile));
}
}
这个组件按官方提供的写法不行,出来的汉字全成了麻将里的白板,还是得用网上的示例,加上字体映射之后可以了。不知道放到linux服务器上会是什么样。
该方案的思路其实是OpenOffice提供软件支持,Java代码又利用jodconverter组件调用OpenOffice,其实和以前的程序调用 com组件是一个思路。而OpenOffice还提供了web服务版本,可以用类似tcp的方式调用来完成生成的工作。
本次测试就采用的是这种方法,因此需要安排OpenOffice软件,安装后在安装目录执行以下命令:
soffice.exe -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard
<dependency>
<groupId>org.apache.directory.studiogroupId>
<artifactId>org.apache.commons.ioartifactId>
<version>2.4version>
dependency>
<dependency>
<groupId>com.artofsolvinggroupId>
<artifactId>jodconverterartifactId>
<version>2.2.1version>
dependency>
<dependency>
<groupId>org.openofficegroupId>
<artifactId>juhartifactId>
<version>3.1.0version>
dependency>
<dependency>
<groupId>org.openofficegroupId>
<artifactId>unoilartifactId>
<version>3.0.0version>
dependency>
package com.hawkon.openoffice;
import com.artofsolving.jodconverter.DocumentConverter;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter;
import java.io.File;
import java.net.ConnectException;
public class WordToPdfTest_openoffice {
public static void wordToPdf(String docFile,String pdfFile) throws ConnectException {
// 源文件目录
File inputFile = new File(docFile);
// 输出文件目录
File outputFile = new File(pdfFile);
if (!outputFile.getParentFile().exists()) {
outputFile.getParentFile().exists();
}
// 连接openoffice服务
OpenOfficeConnection connection = new SocketOpenOfficeConnection(
"127.0.0.1", 8100);
connection.connect();
// 转换word到pdf
DocumentConverter converter = new OpenOfficeDocumentConverter(
connection);
converter.convert(inputFile, outputFile);
// 关闭连接
connection.disconnect();
}
}
poi虽然很强大,但用起来越是最痛苦的,用的组件多,各种版本冲突,各种缺少组件。不知道网上发贴子的那些大神是怎么研究出来哪个版本对应哪个版本的,非常佩服他们。测试的时候我就在想,有没有什么能查询各种Jar包版本依赖关系的网站。如果有,请看客们告诉我一场。
<dependency>
<groupId>org.apache.poigroupId>
<artifactId>poiartifactId>
<version>3.10.1version>
dependency>
<dependency>
<groupId>org.apache.poigroupId>
<artifactId>poi-scratchpadartifactId>
<version>3.10.1version>
dependency>
<dependency>
<groupId>org.apache.poigroupId>
<artifactId>poi-ooxmlartifactId>
<version>3.10.1version>
dependency>
<dependency>
<groupId>fr.opensagres.xdocreportgroupId>
<artifactId>org.apache.poi.xwpf.converter.coreartifactId>
<version>1.0.6version>
dependency>
<dependency>
<groupId>fr.opensagres.xdocreportgroupId>
<artifactId>org.apache.poi.xwpf.converter.pdfartifactId>
<version>1.0.6version>
dependency>
<dependency>
<groupId>fr.opensagres.xdocreportgroupId>
<artifactId>fr.opensagres.xdocreport.itext.extensionartifactId>
<version>2.0.1version>
dependency>
package com.hawkon.poi;
import org.apache.poi.xwpf.converter.pdf.PdfConverter;
import org.apache.poi.xwpf.converter.pdf.PdfOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import java.io.*;
public class WordToPdf_Poi {
public static void wordToPdf(String docFile,String pdfFile) throws IOException {
XWPFDocument document;
InputStream doc = new FileInputStream(docFile);
document = new XWPFDocument(doc);
PdfOptions options = PdfOptions.create();
OutputStream out = new FileOutputStream(pdfFile);
PdfConverter.getInstance().convert(document, out, options);
doc.close();
out.close();
}
}
<dependency>
<groupId>e-icebluegroupId>
<artifactId>spire.docartifactId>
<version>10.11.6version>
<scope>systemscope>
<systemPath>D:/Code/PdfTest/lib/Spire.Doc.jarsystemPath>
dependency>
package com.hawkon.spire;
import com.spire.doc.*;
public class WordToPdf_spire {
public static void wordToPdf(String docFile,String pdfFile){
com.spire.license.LicenseProvider.setLicenseFile("D:\\Code\\PdfTest\\license.elic.xml");
//实例化Document类的对象
Document doc = new Document();
//加载Word
doc.loadFromFile(docFile);
//保存为PDF格式
doc.saveToFile(pdfFile,FileFormat.PDF);
}
}
测试的时候有性能指标,所以我觉得还是把我电脑的硬件参数发一下,大家可以作为参考。
处理器 Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz 2.11 GHz
机带 RAM 16.0 GB (15.8 GB 可用)
系统类型 64 位操作系统, 基于 x64 的处理器
下面依次放出5种方案的转换结果对比,左边为原版,右边为五种方案的转换结果,并且我也给出我的格式保真度评价
从图中可以看出,除表格处有一点错位以外,看出不明显的差别,已经非常厉害了。我给4星。
有点惨不忍睹呀,表格严重错位,甚至有7页变8页的趋势。与原版格式严重失真。但勉强能阅读。我给2星
格式基本保留住了,但是位置错的比较离谱。好在基本不影响阅读。我给3星。
页眉错乱严重,影响阅读,这有跳页的情况出现。我给1星。
和aspose一样,除表格处有一点错位以外,看出不明显的差别,国产软件能做到这种程序非常NICE了。我给4星。
最后的评测结果如下,从转换效果的角度来说,比较满意的是aspose和spire.doc,而开源的转换一些比较简单的文章还可以,但企业开发的时候很多时候是要求PDF格式和WORD文档高度保持一致的。其它三种方案的表现肯定是不够的。
值得一提的是,没想到国产软件spire.doc表现还不错,除性能稍差一点,其它都不错,最重要的是价格还是比较亲民的。
而且这家公司的产品应该是已经走出国门了,希望国产软件可以做出更多的精品,也希望大家多多支持国产软件。
最后声明两点: