JODConverter是一种Java OpenDocument转换器,能够转换不同格式的文档,它依赖于Apache OpenOffice或 LibreOffice ,它为OpenDocument和Microsoft Office提供了最好的免费导入/导出的过滤器。
JODConverter自动支持OpenOffice和LibreOffice提供的所有转换,如下:
JODConverter可以用在这几种地方:
添加下列的依赖到pom.xml
文件中
<properties>
<jodconverter.version>4.1.0jodconverter.version>
properties>
<dependencies>
<dependency>
<groupId>org.jodconvertergroupId>
<artifactId>jodconverter-localartifactId>
<version>${jodconverter.version}version>
dependency>
dependencies>
添加以下信息到你的 build.gradle
ext {
jodconverterVersion = 4.1.0
}
compile "org.jodconverter:jodconverter-local:$jodconverterVersion"
当提到OpenOffice.org(简称为OOo),这通常可以理解为任何来自OOo的办公套件,比如Apache OpenOffice或 LibreOffice 。
为了使用JODConverter你需要有以下配置:
JODConverter所使用的时间值均为毫秒
使用LocalOfficeManager需要设置一些参数。使用JODConverter时,会采用默认配置。虽然这些配置信息不一定是最好的,但是他们更有可能被选中使用。
protNumbers 和 pipeNames
OOo 进程间的通信可以使用TCP sockets 或者 命名管道。命名管道具有不占用TCP端口的优势(存在安全隐患),并且可能会更快一些。然而命名管道需要由JVM加载本地库,这意味着必须在java.library.path
中设置路径,这就是为什么pipeNames
不是默认配置的原因了。由于平台的不同,添加到java/library.path
的路径也不同,但它应该是包含了libjipe
的OOo安装目录。
Default:TCP socket,on port 2002,
// This example will use 4 TCP ports, which will cause
// JODConverter to start 4 office processes when the
// OfficeManager will be started.
OfficeManager officeManager =
LocalOfficeManager.builder()
.portNumbers(2002, 2003, 2004, 2005)
.build();
officeHome
该属性应该设置为OOo的安装目录。若没有配置,则创建OfficeManager时会自动检测,从LibreOffice(优先于OpenOffice)的最新版本开始。
// This example will force JODConverter to use the OpenOffice 4
// installation that can be found using the specified path.
OfficeManager officeManager =
LocalOfficeManager.builder()
.officeHome("D:\\Program Files (x86)\\OpenOffice 4")
.build();
processManager
JODConverter开始处理一个office进程时,就需要使用到进程管理器。当它开始进行这项工作,就必须要检索该进程的PID,以便在需要时能够kill it。默认情况下,JODConverter会根据JODConverter运行的操作系统来选择最佳的进程管理器。但是,在classpath
中发现的,且继承了ProcessManager
接口的进程管理器均可以被使用。
// This example will create an instance of the com.example.foo.CustomProcessManager
// class that will be used by the created OfficeManager.
OfficeManager officeManager =
LocalOfficeManager.builder()
.processManager("com.example.foo.CustomProcessManager")
.build();
workingDir
该属性用来设置office临时文件配置目录。每个office进程启动时,一个文件配置目录将会被创建。当使用InputStream/OutputStream
来转换时,这个目录也会被创建。默认由指定的路径为java.io.tmpdir
templateProfileDir
为了避免进程被中断或者用户使用了另一个OOo实例,LocalOfficeManager会为OOo进程创建一个临时配置文件目录。使用这个属性,你可以提供一个包含个性化设置的临时配置文件目录。OfficeManager会将以其为模板,来生成临时配置文件目录。所以当我们创建新的OOo实例时,都会使用相同的配置。默认情况虾,这个临时的配置文件由OOo使用默认配置来创建,并且其依赖于 -nofirststartwizard
这个命令选项。
killExistingProcess
该属性能够指定,当一个包含相同connection string
的office进程启动,是否杀死一个已经存在的office进程。默认为true
.
processTimeout
当尝试调用一个office进程时(开始/中止),该属性可以设置超时时间,单位为毫秒。默认为120000
(2 minutes)
processRetryInterval
每当尝试调用一个office进程时(开始/中止)的间隙,可用该属性设置延迟,单位为毫秒。默认为250
(0.25 seconds)
taskExecutionTimeout
该属性设置执行一个任务的最大时间,若超过这个时间任务仍未执行,则当前任务被中止且执行下个任务。默认为12000
(两分钟)
maxTasksPerProcess
该属性设置一个office进程在重启之前所能执行的最大任务数。默认为200
个。
disableOpengl
当启动一个新的office进程时(在LibreOffice的情况下),该属性能够指定是否禁止OpenGL。如果OpenGL已经根据office进程使用的用户配置禁用,那么将不会执行任何操作。如果该属性改变,那么office进程必须重启。如果LO进程奔溃,那么你可以尝试测试该属性。默认为false
taskQueueTimeout
该属性用来设置一个任务在转换队列中的最大生存时间。如果等待时间超过最大生存时间或者有OfficeException
异常抛出,则任务将会从队列中移除。默认为30000
(30 seconds)
在你的Java程序中使用JODConverter是非常简单的。接下来的例子展示了执行WORD文档转换成PDF主要代码:
File inputFile = new File("document.doc");
File outputFile = new File("document.pdf");
// Create an office manager using the default configuration.
// The default port is 2002. Note that when an office manager
// is installed, it will be the one used by default when
// a converter is created.
final LocalOfficeManager officeManager = LocalOfficeManager.install();
try {
// Start an office process and connect to the started instance (on port 2002).
officeManager.start();
// Convert
JodConverter
.convert(inputFile)
.to(outputFile)
.execute();
} finally {
// Stop the office process
OfficeUtils.stopQuietly(officeManager);
}
如果想转换成其他格式,可以更改文件名,转换的格式将根据文件的扩展名来决定。比如,将EXCEL文件转换成OpenDocument Spreadsheet格式:
File inputFile = new File("spreadsheet.xls");
File outputFile = new File("spreadsheet.ods");
JodConverter
.convert(inputFile)
.to(outputFile)
.execute();
如果你想使用IO流来替代文件,这个完全没有问题!你仅需要通知JODConverter
输入流和输出流的文件格式即可。比如,将EXCEL文件转换成OpenDocument Spreadsheet格式:
InputStream inputStream = ...
OutputStream outputStream = ...
JodConverter
.convert(inputStream)
.as(DefaultDocumentFormatRegistry.XLS)
.to(outputStream)
.as(DefaultDocumentFormatRegistry.ODS)
.execute();
十分简单,是吧?以上的例子已经能够满足绝大部分开发所需了。
从功能上来说,每开始一个转换,就创建一个新的连接,这是可以接受的。但是从性能上来说,这并不是最好的选择。如果你想把JODConverter整合进你的web应用中,那么你应该初始化一个单例的OfficeManager实例,当app启动时就初始化该实例,app关闭时则停止该实例。
最重要的理念便是,在启动web应用时(使用servlet监听器,Spring上下文或者你选择的其他等效的框架),应该使用一个单例的OfficeManager实例,停止该实例当web应用停止时,并且让所有请求共享该实例。让OfficeManager管理多线程。
在转换一个文档时,JODConverter允许你将加载的资源文档转换成目标文档前修改它。原文件不会被修改,只会修改加载的。当然,你所能做的修改是基于OOo能做的。使用JODConverter进行转换和使用OOo执行修改操作是一致的。
这是一个PageSelectorFilter
实例,这个例子只转换了给定源文档的第二页。
final File inputFile = new File("document.rtf");
final File outputFile = new File("document.html");
final PageSelectorFilter selectorFilter = new PageSelectorFilter(2);
LocalConverter
.builder()
.filterChain(selectorFilter)
.build()
.convert(inputFile)
.to(outputFile)
.execute();
在每次转换中,你可以使用一个以上的过滤器。而且,当目标文件不是PDF时才需要使用这样的过滤器。事实上,将文件转换为pdf,最好使用自定义存储属性:
File inputFile = new File("document.rtf");
File outputFile = new File("document.pdf");
Map filterData = new HashMap<>();
filterData.put("PageRange", "2");
Map customProperties = new HashMap<>();
customProperties.put("FilterData", filterData);
LocalConverter
.builder()
.storeProperties(customProperties)
.build()
.convert(inputFile)
.to(outputFile)
.execute();
JODConverter提供了一些过滤器,但是你可以自己实现任何你需要的过滤器(你的过滤器必须继承Filter
接口,并负责在过滤器链中调用下一个过滤器)。
JODConverter自动转换实际上是由OOo提供的。这意味着,如果你可以使用OOo将ABC格式的文档转换成XYZ文档,那么你可以使用JODConverter做到相同的操作。OpenOffice Wiki官网中可以查找一个有用的列表。LibreOffice Wiki没有提供这样一个列表,但其应该与Apache OpenOffice 大部分一致。
也就是说,JODConverter维护了一个常用格式的注册表,关联文件的扩展名,mime类型。这些预定义的转换如下表所示:
HTML可以作为输入格式,但是你不要期望OOo可以像Chrome或者IE完整得将网页展示出来(没有样式)。像打印机那样简单友好的工作也是不错的。
HTML可以作为输出格式使用。但是当所有其他输出格式往往只产生一个文件时,HTML可以产生多个文件。事实上除了HTML,输入文档中包含的任何图片也将保存在相同的目录中。这个在你的代码中需要格外的小心,特别是在web环境中。