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から取得できる。