LibreOffice の力で PDF エクスポートする librepdf

現在大きな仕事を終えて、今は自身の知識の棚おろし中・・ノウハウの結晶化をしておきたいという個人的な動機から librepdf なんていう gem を公開しました。
https://github.com/hamajyotan/librepdf
ざっくりいうと、 LibreOffice の機能を用いて各種ファイルから PDF エクスポートできるというシロモノで、 MS Office 文書なんかも OK です。JRuby 専用、LibreOffice の UNO APIJava で叩いて、それを Ruby から使えるようにしています。まだまだまだ不安定ですが、きっと開示したほうがハッピーだなと思った次第です。

インストール

$ gem install librepdf

事前に LibreOffice をサービスとして起動する

$ /opt/libreoffice3.5/program/soffice.bin \
  --accept="socket,host=127.0.0.1,port=8100,tcpNoDelay=1;urp;" \
  --headless \
  --invisible \
  --nodefault \
  --nofirststartwizard \
  --nolockcheck \
  --nologo \
  --norestore

起動したら 8100 ポートのリスンを確認

$ netstat -ant | grep 8100
tcp        0      0 127.0.0.1:8100              0.0.0.0:*                   LISTEN

使い方サンプル

/home/hamajyotan/test.doc から、 /home/hamajyotan/test.pdf を作成
require 'rubygems'
require 'librepdf'

con = Connection.new "host" => "127.0.0.1", "port" => 8100
doc = con.load "file:///home/hamajyotan/test.doc"
doc.convert_pdf "file:///home/hamajyotan/test.pdf"
doc.close
con.close
上記の後処理省力化的な書き方版
require 'rubygems'
require 'librepdf'

Librepdf::Connection.new "host" => "127.0.0.1", "port" => 8100 do |con|
  con.load "file:///home/hamajyotan/test.doc" do |doc|
    doc.convert_pdf "file:///home/hamajyotan/test.pdf"
  end
end
僕はブレースの方が好み
require 'rubygems'
require 'librepdf'

Librepdf::Connection.new("host" => "127.0.0.1", "port" => 8100) { |con|
  con.load("file:///home/hamajyotan/test.doc") { |doc|
    doc.convert_pdf "file:///home/hamajyotan/test.pdf"
  }
}
パスワード付きファイルを開く
require 'rubygems'
require 'librepdf'

Librepdf::Connection.new("host" => "127.0.0.1", "port" => 8100) { |con|
  con.load("file:///home/hamajyotan/test.doc", "Password" => "SECRETPASSWORD") { |doc|
    doc.convert_pdf "file:///home/hamajyotan/test.pdf"
  }
}
ページを指定して PDF エクスポート

ページ範囲外の指定は例外が投げられます。

require 'rubygems'
require 'librepdf'

Librepdf::Connection.new("host" => "127.0.0.1", "port" => 8100) { |con|
  con.load("file:///home/hamajyotan/test.doc") { |doc|
    doc.convert_pdf "file:///home/hamajyotan/test1.pdf", "FilterData" => { "PageRange" => "1-1" }
    doc.convert_pdf "file:///home/hamajyotan/test2.pdf", "FilterData" => { "PageRange" => "2-2" }
    doc.convert_pdf "file:///home/hamajyotan/test3.pdf", "FilterData" => { "PageRange" => "3-3" }
  }
}

クラスの説明

Librepdf::Connection

LibreOffice への接続を担う

  • #initialize options = {}
    • options ハッシュへは、 "host" と "port" が受理可能
    • ブロックを渡すと、ブロック引数に自身のインスタンスを渡してブロック終了時にクローズする
  • #closed?
    • 接続を閉じていれば true, そうでなければ false
  • #close
    • 接続を閉じる
  • #load input_url, options = {}
Librepdf::Document

LibreOffice にロードされたドキュメントを示す、Librepdf::Connection#load の返り値として得る以外にインスタンス生成方法は無い。
正確には、このクラスのインスタンスではなく、ドキュメント種類に応じたサブクラスのインスタンスが生成される。例えば Librepdf::Document::Calc など。

  • #closed?
    • 接続を閉じていれば true, そうでなければ false
  • #close
    • 接続を閉じる
  • #convert_pdf output_url, options = {}
    • PDF エクスポートを行う
    • options ハッシュへは、 UNO の storeToURL の第2引数に渡すプロパティの一部が設定可能

今後やりたいこと