WebページをPDFに出力する
Symfony2でWebページをPDF出力するバンドルを紹介します。
今回試した環境は以下のとおりです。
- 開発環境:Mac OSX Mervericks
- ステージング環境:Ubuntu 12.04
インストール
composerでインストールして、設定を追加します。
composer
php composer.phar require "knplabs/knp-snappy-bundle:1.0.*@dev"
AppKernel.php
<?php
public function registerBundles()
{
$bundles = array(
//...
new Knp\Bundle\SnappyBundle\KnpSnappyBundle(),
//...
config.yml
knp_snappy:
pdf:
enabled: true
binary: /usr/local/bin/wkhtmltopdf
options: []
image:
enabled: true
binary: /usr/local/bin/wkhtmltoimage
options: []
依存コマンド wkhtmltopdf のインストール
http://wkhtmltopdf.org/からダウンロードしてインストールします。
※ homebrewでもインストールできますが、バージョンが古いためKnpSnappyBundleでは動作しません。
インストールしたらバージョンを確認しましょう。
wkhtmltopdf -V
wkhtmltopdf 0.12.1 (with patched qt)
PDFを出力してみましょう
1ページ
<?php
$container->get('knp_snappy.pdf')->generate(
'http://xxx.com',
'/path/to/the/file.pdf'
);
複数ページ
<?php
$container->get('knp_snappy.pdf')->generate(
array('http://xxx.com', 'http://www.zzz.com'),
'/path/to/the/file.pdf'
);
これでひとまず完了ですね。
KnpSnappyBundleの仕組み
1) knp_snappy.pdf –> wkhtmltopdf
knp_snappy.pdfサービスは渡されたURLをwkhtmltopdf
コマンドに渡します。
wkhtmltopdf --lowquality 'http://xxx.com' '~/output.pdf'
2) wkhtmltopdf –> Qt
Qt(キュート)のQtWebKitモジュールを使ってWebページがレンダリングされます。
3) ステータスコードが返される
EditCode | Explanation |
---|---|
0 | All OK |
1 | PDF generated OK, but some request(s) did not return HTTP 200 |
2 | Could not something something |
X | Could not write PDF: File in use |
Y | Could not write PDF: No write permission |
Z | PDF generated OK, but some JavaScript requests(s) timeouted |
A | Invalid arguments provided |
B | Could not find input file(s) |
C | Process timeout |
オプションの変更
config.ymlでオプションを設定することができます。 スピード優先のおすすめ設定はこれです。
knp_snappy:
pdf:
enabled: true
binary: /usr/local/bin/wkhtmltopdf
options:
- { name: page-size, value: A4 }
- { name: encoding, value: UTF-8 }
- { name: disable-javascript, value: true } # javascriptを実行しない
- { name: no-background, value: true } # バックグラウンド実行
- { name: dpi, value: 80 } # 解像度を下げる
- { name: allow, value: %kernel.root_dir%/../web } # 自プロジェクトのページを印刷する場合に、アセットをローカルから検索
一時的にオプションを変更して出力する場合はgenerate()
の第3引数を使用します。
<?php
$container->get('knp_snappy.pdf')->generate(
'http://xxx.com',
'/path/to/the/file.pdf',
array('page-size' => 'B4')
);
ステージング環境で実行
デスクトップ環境のないステージング環境とローカルの開発環境の両方で動作させるには、コマンドをparameters.yml
で切替えられるようにします。
config.yml
knp_snappy:
pdf:
enabled: true
binary: %command_pdf%
options: []
image:
enabled: true
binary: %command_image%
options: []
parameters.yml 開発環境
parameters:
command_pdf: wkhtmltopdf
parameters.yml ステージング環境
parameters:
command_pdf: xvfb-run --auto-servernum --server-num=1 wkhtmltopdf
Xvfb (X virtual framebuffer)
サーバーに別途インストールしてください。 仮想環境でXの入出力をシュミレートするものです。最大99個の仮想環境が作成できます。 今回は仮想環境の細かいオプションは指定しないので空いている番号を検索して使います。
--server-num=1
: 仮想環境は1番目以降を使う--auto-servernum=1
: 自動的に番号を振る
まとめ
Symfony2でPDF出力をサポートしてくれるバンドルはいくつか試しましたが、日本語がきちんと表示されないものが多かったです。 KnpSnappyBundleはレンダリングを外部コマンドに任せているため設定やインストールが少し面倒に感じますが、ブラウザのPDF出力とほぼ同じ結果が得られるのがいいですね。