環境
- OS
- 開発PC: macOS Mojave
- サーバー: Amazon Linux
- ruby 2.6.1
- Rails 5.2.2
初期段階
ミニマムで実装すると以下のようになります。
また、layout
で指定するファイルはapp/views/layouts
に配置する必要があります。
src
├── app
│ ├── assets
│ │ └── stylesheets
│ │ └── sample
│ │ └── sample.sass
│ ├── controller
│ │ └── sample
│ │ └── sample_controller.rb
│ └── views
│ ├── sample
│ │ ├── sample.html.slim
│ └── layouts
│ └── pdf_for_sample.html.slim
└── Gemfile
def generate_pdf
respond_to do |format|
format.html { redirect_to sample_generate_pdf_path(format: :pdf)}
format.pdf do
if params[:debug].present?
render pdf: 'sample',
title: 'sample.pdf',
encoding: 'UTF-8',
layout: 'pdf_for_sample.html.slim',
template: "sample/sample.html.slim",
show_as_html: params[:debug].present?
else
render pdf: 'sample',
title: 'sample.pdf',
encoding: 'UTF-8',
layout: 'pdf_for_sample.html.slim',
template: "sample/sample.html.slim",
show_as_html: params[:debug].present?
end
end
end
end
doctype html
html[lang="ja" xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" dir="ltr"]
head
/ メインのcss
= wicked_pdf_stylesheet_link_tag 'sample/sample', media: 'all'
body
.sample
.sample-text コンテンツ
# 空っぽ
gem 'wicked_pdf'
gem 'wkhtmltopdf-binary'
layoutとtemplateを使い分ける
最初は違いがわかりにくかったのですが、layout
のファイルは共通、template
は個別のHTMLを描写するものとし、layout
からtemplate
を呼び出す作りにするのが良さそうです。
doctype html
html[lang="ja" xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" dir="ltr"]
head
/ メインのcss
= wicked_pdf_stylesheet_link_tag 'sample/sample', media: 'all'
body
= yield
.sample
.sample-text コンテンツ
A4横向き&pdfファイル全体に背景画像を使いたい
筆者の場合A4かつ横向きで生成する必要があったので、page_size
とorientation
を指定します。
(page_sizeはデフォルトでA4なので指定は不要ですが、可読性のため明示的に指定しました)
def generate_pdf
respond_to do |format|
format.html { redirect_to sample_generate_pdf_path(format: :pdf)}
format.pdf do
if params[:debug].present?
render pdf: 'sample',
title: 'sample.pdf',
encoding: 'UTF-8',
orientation: 'Landscape', #横向き
page_size: 'A4',
margin: { top: 0,
bottom: 0,
left: 0,
right: 0 },
layout: 'pdf_for_sample.html.slim',
template: "sample/sample.html.slim",
show_as_html: params[:debug].present?
else
render pdf: 'sample',
title: 'sample.pdf',
encoding: 'UTF-8',
orientation: 'Landscape', #横向き
page_size: 'A4',
margin: { top: 0,
bottom: 0,
left: 0,
right: 0 },
layout: 'pdf_for_sample.html.slim',
template: "sample/sample.html.slim",
show_as_html: params[:debug].present?
end
end
end
end
次にpdf全体を覆う背景画像を当て込みます。
デフォルトでmarginが設定されているので初期化し、かつA4に合うよう調整した結果、heightを991px
に設定しました。
.sample
background: sample.png
background-size: cover
height: 991px
画面遷移を行わず、PDFのファイルダウンロードまで行いたい
筆者のPJでは生成したpdfファイルはユーザーのPCにダウンロードされる想定でしたが、このままだと、「ボタンクリックなどでPDF生成実行→pdfファイル画面へ遷移→ダウンロードボタンをクリック→ファイルがダウンロードされる」と言うフローになり、やや煩雑です。
上記を「ボタンクリックなどでPDF生成実行→ファイルがダウンロードされる」と言うフローにするため、以下の記述に変更します。
def generate_pdf
respond_to do |format|
format.html { redirect_to sample_generate_pdf_path(format: :pdf) }
format.pdf do
if params[:debug].present?
render pdf: 'sample',
title: 'sample.pdf',
encoding: 'UTF-8',
orientation: 'Landscape',
page_size: 'A4',
margin: { top: 0,
bottom: 0,
left: 0,
right: 0 },
layout: 'pdf_for_sample.html.slim',
template: "sample/sample.html.slim",
show_as_html: params[:debug].present?
else
pdf = render_to_string pdf: 'sample',
title: 'sample.pdf',
encoding: 'UTF-8',
orientation: 'Landscape',
page_size: 'A4',
margin: { top: 0,
bottom: 0,
left: 0,
right: 0 },
layout: 'pdf_for_sample.html.slim',
template: "sample/sample.html.slim",
show_as_html: params[:debug].present?
send_data pdf, filename: "sample.pdf"
end
end
end
end
filename: "sample.pdf"
でダウンロードされる際のファイル名が指定可能です。
Amazon LinuxでRuntime errorになる
環境依存問題その1
ローカルで動作確認をしていざデプロイ!と思ったらPDF生成実行で500エラー(Runtime error
)となり動かない...
どうやら、AmazonLinuxは動作環境外のようでした。
調べてみるとAmazonLinux対応版のブランチがあるようなので、指定したら正常に動作しました。
gem 'wicked_pdf'
gem 'wkhtmltopdf-binary',
git: 'https://github.com/entretechno/wkhtmltopdf_binary_gem',
branch: 'amazon-linux'
日本語が文字化けする
環境依存問題その2
PDF生成の際にはクライアントではなくサーバー側のフォントを参照するらしく、日本語が文字化けしてまともに動かない状態に。
そのためサーバーに日本語フォントをインストールした上で、cssからスタイルに適用します。
今回はyumで手軽にインストール可能なIPAフォントを利用しました。
(本当はnotoなどのgoogleフォントが使えれば尚良かったのですが、筆者の環境では正常に読み込めませんでした)
sudo yum -y install ipa-gothic-fonts ipa-mincho-fonts
.sample
background: sample.png
background-size: cover
height: 991px
.sample-text
font-family: 'IPAMincho', 'IPA明朝'
また、serif
、san-serif
は、フォントをインストールしない状態でも描画可能だったので、試してみるといいかもしれません。
最終形
上記をまとめると以下になります。
def generate_pdf
respond_to do |format|
format.html { redirect_to sample_generate_pdf_path(format: :pdf) }
format.pdf do
if params[:debug].present?
render pdf: 'sample',
title: 'sample.pdf',
encoding: 'UTF-8',
orientation: 'Landscape',
page_size: 'A4',
margin: { top: 0,
bottom: 0,
left: 0,
right: 0 },
layout: 'pdf_for_sample.html.slim',
template: "sample/sample.html.slim",
show_as_html: params[:debug].present?
else
pdf = render_to_string pdf: 'sample',
title: 'sample.pdf',
encoding: 'UTF-8',
orientation: 'Landscape',
page_size: 'A4',
margin: { top: 0,
bottom: 0,
left: 0,
right: 0 },
layout: 'pdf_for_sample.html.slim',
template: "sample/sample.html.slim",
show_as_html: params[:debug].present?
send_data pdf, filename: "sample.pdf"
end
end
end
end
doctype html
html[lang="ja" xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" dir="ltr"]
head
/ メインのcss
= wicked_pdf_stylesheet_link_tag 'sample/sample', media: 'all'
body
= yield
.sample
.sample-text コンテンツ
.sample
background: sample.png
background-size: cover
height: 991px
.sample-text
font-family: 'IPAMincho', 'IPA明朝'
gem 'wicked_pdf'
gem 'wkhtmltopdf-binary',
git: 'https://github.com/entretechno/wkhtmltopdf_binary_gem',
branch: 'amazon-linux'