Kuchitama Tech Note

はてな記法がいつまでたっても覚えられないので、はてなダイアリーからマークダウンが使えるこっちに引っ越してきました。

Play2.0Scalaでファイルダウンロード

目的

play2.0Scalaでplay1の時にあったrenderBinaly的な事をしてcsvファイルをダウンロードしたかったので、調べた結果のまとめ。

参考

http://www.playframework.org/documentation/2.0/ScalaStream

とりあえず、このエントリ読むよりも上記公式情報を読むべき。 Serving files の項を読めば、ここでやる内容は十分。 英語が辛いとか、とりあえず動けばいい人だけ、ここから下を読んでください。

とりあえずダウンロード

play2.0 scalacsvファイルをダウンロードするサンプル

conf/routes

# Home page
GET  /            controllers.Application.index
GET  /download    controllers.Application.download

app/controllers/FileDownloadController.scala

package controllers

import play.api._
import play.api.mvc._
import java.io.File

object Application extends Controller {
  
  def index = Action {
    Ok(views.html.index("Your new application is ready."))
  }
  
  def download = Action {
    val file = new File("hoge.csv")
    
    Ok.sendFile(file)
  }
}

このサンプルだと、ダウンロードできるファイル名は、uriからdownloadとなってしまう。 ファイル名そのままのhoge.csvとなります。 公式サイトだと、サンプルとしてPDFをダウンロードしているが、

This helper will also compute the Content-Type header from the file name, and add the Content-Disposition header to specify how the web browser should handle this response. The default is to ask the web browser to download this file by adding the header Content-Disposition: attachment; filename=fileToServe.pdf to the HTTP response.

とあるように、デフォルトはファイル名が自動で指定されるらしい。 なのに、ファイルがcsvだとうまくいかない。

ファイル名を指定

なぜか自動で解決してくれないので、明示的にファイル名を指定する。

app/controllers/FileDownloadController.scala

…

object Application extends Controller {
  
  …
  
  def download = Action {
    val file = new File("hoge.csv")
    
    Ok.sendFile(
      content = file,
      fileName = _ => "fuga.csv"
    )
  }
}

こうすると、ダウンロード出来るファイル名をfuga.csvのように、元のファイル名に関係なく指定する事が出来る。


一部、勘違いがあったので修正しました。 2013/01/12