JODConverterでExcelファイルからpdfファイルを生成する例。
|
JODConverterはLibreOffice(あるいはApache OpenOffice)を使ってPDFを生成する。
したがって、実行環境にLibreOffice(あるいはOpenOffice)がインストールされている必要がある。
JODConverter 4.1には、LibreOffice(やOpenOffice)へのアクセス方法としてLocalConverterとOnlineConverterの2種類がある。
LocalConverterは実行したマシン上のLibreOffice(やOpenOffice)を使用する。
OnlineConverterは、別のサーバーを用意し、そのマシン上のLibreOffice(やOpenOffice)を使用する。
JODConverter 4.0と4.1ではOfficeManagerやDocumentConverterの生成方法およびconvertメソッドの使用方法が変わっている。
4.1ではdocuments4jの方法に合わせたように見受けられる。
JODConverter(バージョン4)はMavenリポジトリーから取得できる。
Gradleの場合は以下のような感じ。
apply plugin: 'java'
apply plugin: 'eclipse'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile('org.jodconverter:jodconverter-local:4.1.0') // LocalConverter
compile('org.jodconverter:jodconverter-online:4.1.0') // OnlineConverter
compile('ch.qos.logback:logback-classic:1.1.11')
}
task wrapper(type: Wrapper) {
gradleVersion '4.1'
jarFile file('.buildtools/gradlew.jar')
}
slf4jが入っていないと、実行時に以下のようなログが出力される。
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
logbackを入れておけば(一緒にslf4jも入るので)このログは出なくなる。
logbackの設定ファイルも一緒に作っておけば完璧。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE logback>
<configuration>
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<target>System.out</target>
<encoder>
<pattern>%d{HH:mm:ss} %-5level %msg%n</pattern>
</encoder>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
JODConverterを実行するには、実行環境にLibreOffice(あるいはOpenOffice)がインストールされている必要がある。
package com.example.jod; import java.io.File; import org.jodconverter.DocumentConverter; import org.jodconverter.LocalConverter; import org.jodconverter.office.LocalOfficeManager; import org.jodconverter.office.OfficeException; import org.jodconverter.office.OfficeManager;
public class JodLocalExample {
public static void main(String... args) throws OfficeException {
OfficeManager officeManager = LocalOfficeManager.make();
DocumentConverter converter = LocalConverter.make(officeManager);
// OfficeManager officeManager = LocalOfficeManager.builder().build();
// DocumentConverter converter = LocalConverter.builder().officeManager(officeManager).build();
System.out.println("officeManager start");
officeManager.start();
try {
System.out.println("convert start");
File excelFile = new File("D:/data/dq10/DQ10.xls");
File pdfFile = new File("D:/temp/jodconverter/dq10.pdf");
converter.convert(excelFile).to(pdfFile).execute();
System.out.println("convert end");
} finally {
officeManager.stop();
}
}
}
最初にOfficeManagerを生成する。これがLibreOfficeを呼び出す役割を持っていると思われる。
インスタンス生成後にstartさせる。
(実行できるようになるまで数秒だけ時間がかかる)
あとはDocumentConverterのconvert〜executeメソッドを呼び出すだけ。
(ドキュメントフォーマットはFileの拡張子から判断される)
JODConverter 4.1では、Fileの他にInputStream, OutputStreamを指定することも出来る。
import java.io.InputStream; import java.io.OutputStream; import org.jodconverter.document.DocumentFormat; import org.jodconverter.document.DocumentFormatRegistry;
DocumentFormatRegistry registry = converter.getFormatRegistry();
DocumentFormat xlsFormat = registry.getFormatByExtension("xls");
DocumentFormat pdfFormat = registry.getFormatByExtension("pdf");
try (InputStream is = 〜; OutputStream os = 〜) {
converter.convert(is).as(xlsFormat).to(os).as(pdfFormat).execute();
}
ただし、内部では結局ファイル経由なので、場合によってはFileを使う方がいいかもしれない。
生成されるpdfは、Excelファイル内の全シートが対象になる。
ページのサイズは、Excelファイルの印刷設定が使われるようだ。
↓実行例
officeManager start 09:41:22 INFO Submitting task 'Start' and waiting... 09:41:22 INFO Starting process with acceptString 'socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;StarOffice.ServiceManager' and profileDir 'C:\Users\HISHID~1\AppData\Local\Temp\.jodconverter_socket_host-127.0.0.1_port-2002_tcpNoDelay-1' 09:41:23 INFO Started process; pid = 3188 09:41:24 INFO Connected: 'socket,host=127.0.0.1,port=2002,tcpNoDelay=1' convert start 09:41:24 INFO Executing local conversion task... convert end 09:41:31 INFO Stopping the office manager pool... 09:41:31 INFO Submitting task 'Stop' and waiting... 09:41:31 INFO Disconnected: 'socket,host=127.0.0.1,port=2002,tcpNoDelay=1' 09:41:31 INFO process exited with code 0 09:41:31 INFO Office manager stopped
OfficeManagerをstartさせないと、以下のような例外が発生する。
Exception in thread "main" java.lang.IllegalStateException: This office manager is not running. at org.jodconverter.office.AbstractOfficeManagerPool.execute(AbstractOfficeManagerPool.java:95) at org.jodconverter.office.LocalOfficeManager.execute(LocalOfficeManager.java:36) at org.jodconverter.LocalConverter$LocalConversionJob.doExecute(LocalConverter.java:174) at org.jodconverter.job.AbstractConversionJob.execute(AbstractConversionJob.java:57) at com.example.jod.JodExample410.main(JodExample410.java:31)
OnlineConverterを使う場合、DocumentConverterの生成方法が違うだけで、後はLocalConverterと同じ。
import org.jodconverter.DocumentConverter; import org.jodconverter.OnlineConverter; import org.jodconverter.office.OfficeManager; import org.jodconverter.office.OnlineOfficeManager;
String url = "http://localhost:8080/api/jodconverter";
OfficeManager officeManager = OnlineOfficeManager.make(url);
DocumentConverter converter = OnlineConverter.make(officeManager);
// OfficeManager officeManager = OnlineOfficeManager.builder().urlConnection(url).build();
// DocumentConverter converter = OnlineConverter.builder().officeManager(officeManager).build();
urlConnectionでサーバーのURLを指定する。
OnlineConverterを使う場合は、OnlineConverterの要求を受け取って実際の変換を行うサーバーアプリケーションが必要となる。
(documents4jの場合はサーバーアプリケーションが提供されているが、JODConverterではそのような物は無いようなので、自作する必要がある)
参考: sbraconnierさんのjodconverter-sample-webapp
Spring Boot(jodconverter-spring-boot-starter)で作ると以下のようになる。
compile('org.jodconverter:jodconverter-spring-boot-starter:4.1.0')
jodconverter.enabled=true
package com.example.demo.jodconverter; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import org.apache.commons.io.FilenameUtils; import org.jodconverter.DocumentConverter; import org.jodconverter.document.DocumentFormat; import org.jodconverter.document.DocumentFormatRegistry; import org.jodconverter.office.OfficeException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.Resource; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile;
@RestController
public class JodConverterController {
@Autowired
private DocumentConverter documentConverter;
@RequestMapping(path = "/api/jodconverter/lool/convert-to/{outputExtension}", method = RequestMethod.POST)
public Resource convert(@RequestParam("data") MultipartFile file, @PathVariable("outputExtension") String outputExtension) throws IOException, OfficeException {
String inputExtension = FilenameUtils.getExtension(file.getOriginalFilename());
DocumentFormatRegistry registry = documentConverter.getFormatRegistry();
DocumentFormat inputFormat = registry.getFormatByExtension(inputExtension);
if (inputFormat == null) {
inputFormat = registry.getFormatByExtension("xlsx");
}
DocumentFormat outputFormat = registry.getFormatByExtension(outputExtension);
ByteArrayOutputStream os = new ByteArrayOutputStream();
try (InputStream is = file.getInputStream()) {
documentConverter.convert(is).as(inputFormat).to(os).as(outputFormat).execute();
}
return new ByteArrayResource(os.toByteArray());
}
}
OnlineOfficeManager生成時のURLに「http://localhost:8080/api/jodconverter」を指定したとき、
実際のリクエストURLは「http://localhost:8080/api/jodconverter/lool/convert-to/pdf」のようになる。
また、ファイル本体は「data」という名前(のマルチパートファイル)で取得できる。
変換元ファイルの種類は、MultipartFileのoriginalFilenameの拡張子から取得できる。
ただし、クライアント側でFileでなくInputStreamでデータを指定した場合は、ファイル名が一時ファイルのものになっているので(JODConverter
4.1.0では)拡張子は「tmp」になる。
(拡張子tmpのDocumentFormatは無いので、上記の例では強制的に「xlsx」にしている)
変換先ファイルの種類はリクエストURLから取得できる。