今回は、Scala言語ベースのWebフレームワークである、LiftをつかってPDF生成をしてみたいと思います。
最近では,foursquareのような有名サイトなどもLiftで構築されているようです.
今回もsbtが必要になってきます.sbtについては公式サイトか以前の記事に添付したzipに同梱してあるものなどを利用してください。
手順は次の通りです.
- 1. sbtを準備する
- 2. LiftのGetting startedページにあるアーカイブ(zip or tar)をダウンロードし,展開する
- 3. 下記コードとHTMLを上記ディレクトリへ追加する
- 4. sbtでupdateを実行する
- 5. sbtでjetty-runを実行する
出力例は次のとおりです.
本Webアプリは、始めの画面は次のようなものになります.
まず,左側にあるSign Upをクリックし,ユーザ情報を登録します.
ユーザ情報の登録が完了すると,自動的にログインされ,左下にWelcomeと表示されます.
この状態でPDFを生成ボタンをクリックすると,ログインしているユーザの情報が透かしとして印字されたPDFがサーバのテンポラリディレクトリ内に出力されます.
基本的にLiftの場合は,ビューの部分を(一部Liftのタグが混入した)XHTMLで記述し,そのビューへ流し込むデータの作成と,フォームからの入力情報を処理するためのSnippetコードを組み合わせて,Webアプリを作成していきます.
Lift の Snippet ソースコードは次のようになります.
こちらのファイルは新規作成します.
- 《 src/main/scala/code/snippet/GeneratePDF.scala 》
-
package code.snippet import scala.xml.{ NodeSeq, Text } import net.liftweb.util._ import net.liftweb.common._ import net.liftweb.http.SHtml._ import net.liftweb.http.js.JsCmds._ import net.liftweb.util.Helpers._ import java.io.{ StringReader, File } import java.util.Hashtable import javax.xml.parsers.DocumentBuilderFactory import org.xml.sax.InputSource import com.brainsellers.xml.JaxpXML import com.brainsellers.xml.page.PDFEngine import com.brainsellers.xml.datatypes.{ HashtableType, RecordType } import code.lib._ import code.model._ class GeneratePDF { val layoutXml = <Layout width="210mm" height="297mm"> <Star Radius="70mm" FillColor="#99ccff" X="105mm" Y="148.5mm"/> <watermark fit="horizon" align="vertical" text-align="center" rate="80" line-align="center"> <watermark-text name="watermarkText1" font-color="red" text-rendering="stroke"></watermark-text> </watermark> </Layout> def nodeSeqToDocument(xml: NodeSeq) = DocumentBuilderFactory.newInstance.newDocumentBuilder.parse( new InputSource(new StringReader(xml.toString))) def getPDF(in: NodeSeq): NodeSeq = { bind("getPDF", in, "button" -> ajaxButton(Text("PDFを生成"), { () => { val name = User.currentUser.dmap("Guest") { _.niceName } val file = File.createTempFile("generate_pdf_", ".pdf") file.deleteOnExit() val ht = new Hashtable[String, String] ht.put("watermarkText1", name) val bizLib = new JaxpXML(nodeSeqToDocument(layoutXml), file.getAbsolutePath()) bizLib.parse bizLib.calcDataSize bizLib.toPDF(ht) bizLib.close SetHtml("getPDF-div", Text("PDFの生成が完了しました。")) } })) } }
- 26行: レイアウト定義(透かしと星)を行っています.
- 34行: JavaのXML型からScalaのXML型へ変換しています.
- 38行: PDFを生成ボタンが押された際の動作を定義しています.
HTML テンプレートは次のようになります.
こちらのファイルは,既存のファイルを次のものに置き換えます.
- 《 src/main/webapp/index.html 》
-
<lift:surround with="default" at="content"> <lift:generatePDF.getPDF> <div id="getPDF-div"></div> <getPDF:button></getPDF:button> </lift:generatePDF.getPDF> </lift:surround>
- 1行: デフォルトのテンプレートを適用しています.
- 2行: SnippetのGeneratePDFクラスのgetPDFメソッドとマッピングさせています.
- 3行: Snippetから文字列を設定するための領域を定義しています.
- 4行: ボタンを定義しています.
今回はサーバ上にPDFファイルが出力されていますが,次回はブラウザからダウンロードするように修正していきたいと思います.