node.jsからPhantomJSを使ってPDFを生成する
昨日はPhantomJSをインストール、コマンドラインからPDFや画像を生成してみました。
今日は実際の用途に使われそうな、node.js(+ ExpressJS)からPhantomJSを使う方法を検証してみました。
例によってプロジェクトの作成から行います。なお、PhantomJS自体はインストールされている前提で行います。
プロジェクトの作成
node-phantomを使いました。
$ express -e phantom_sample/ $ cd phantom_sample/ $ npm install $ npm install node-phantom --save $ mkdir output
app.js
至って普通です。ルーティングで'/pdf'を追加しただけです。
var express = require('express') , routes = require('./routes') , http = require('http') , path = require('path'); var app = express(); app.configure(function(){ app.set('port', process.env.PORT || 3000); app.set('views', __dirname + '/views'); app.set('view engine', 'ejs'); app.use(express.favicon()); app.use(express.logger('dev')); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(path.join(__dirname, 'public'))); }); app.configure('development', function(){ app.use(express.errorHandler()); }); app.get('/', routes.index); app.get('/pdf', routes.pdf); http.createServer(app).listen(app.get('port'), function(){ console.log("Express server listening on port " + app.get('port')); });
views/index.ejs
[追記]
<meta charset="UTF-8">
の記述が無いと日本語が化けました。
routes/index.js
exports.pdfを追加します。
内容としては、
- 元になるHTMLファイルをoutputディレクトリに生成(res.render())
- 生成したHTMLファイルからPDFファイルを作成(page.render())
- 生成したPDFをブラウザに出力(res.send())
となります。
exports.pdf = function(req, res){ res.render('index', { title: 'Express' }, function(err, html){ //HTML書き込み var fs = require('fs'); var filename = 'output/index.html'; fs.writeFile(filename, html, function (err) { if (err) throw err; //PDF作成 var phantom = require('node-phantom'); phantom.create(function(err, ph) { if (err) throw err; ph.createPage(function(err, page) { if (err) throw err; //page.set('viewportSize', { width: 600, height: 600 }); page.set('paperSize', { format: "A4", orientation: "portrait", margin: {left:"2.5cm", right:"2.5cm", top:"1cm", bottom:"1cm"} }); page.open(filename, function(err, status) { var pdffile = 'output/index.pdf'; page.render(pdffile); page.close(function(){ var fs = require('fs'); fs.readFile(pdffile, function (err, data) { if (err) throw err; res.set({ 'Content-Type': 'application/pdf', 'Content-Disposition': 'attachment; filename="downloaded.pdf"' }); res.send(data); }); }); ph.exit(function(){ console.log('exit'); }); }); }); }); }); }); };
ドキュメントが揃ってないので、正直手探りでした。
page.set()
で用紙サイズやらを設定するのは、test/testpagesetget.jsにありました。他の項目はそちらを参照ください。
ph.exit()
にコールバックが設定してあるのは、page.close()で問題なさそうですが、念のためこちらでres.send()
した方が良いのかもという理由で残してあります。
直URIでダウンロードさせるだけなら、publicディレクトリにPDFを生成して、生成後にリダイレクトさせれば良いと思います。