S-JIS[2017-11-04] 変更履歴

JODConverter 4.1.0サンプル

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の場合は以下のような感じ。

build.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の設定ファイルも一緒に作っておけば完璧。

src/main/resources/logback.xml:

<?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)がインストールされている必要がある。


LocalConverterの例

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の例

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を使う場合は、OnlineConverterの要求を受け取って実際の変換を行うサーバーアプリケーションが必要となる。
documents4jの場合はサーバーアプリケーションが提供されているが、JODConverterではそのような物は無いようなので、自作する必要がある)

参考: sbraconnierさんのjodconverter-sample-webapp

Spring Bootjodconverter-spring-boot-starter)で作ると以下のようになる。

spring-boot-demo/build.gradle:

	compile('org.jodconverter:jodconverter-spring-boot-starter:4.1.0')

spring-boot-demo/src/main/resources/application.properties:

jodconverter.enabled=true

spring-boot-demo/src/main/java/com/example/demo/jodconverter/JodConverterController.java:

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


JODConverterへ戻る / 技術メモへ戻る
メールの送信先:ひしだま