Play Framework でArray[Byte]をそのままHTTP Responseで返す方法
データベースから引っ張ってきたBlobとかをそのままHTTPレスポンスでファイルとして返したいときとかありますよね。Playはローカルのファイルを指定する簡単な方法(Ok.sendFile)はあるのですが、Array[Byte]をbodyに入れたい場合、自力でCONTENT_LENGTHを設定したりとか、ちょっとめんどいですね。
なので、その辺簡単にできるようなコードを書いてみました。
import play.api.mvc.SimpleResult import play.api.libs.iteratee.Enumerator import play.api.http.HeaderNames object current extends current trait current { implicit class ByteContentResult(self: SimpleResult) { def withByteContent(contentType: String, filename: Option[String], content: Array[Byte]): SimpleResult = { val newHeader = self.header.copy( headers = self.header.headers ++ Map(HeaderNames.CONTENT_LENGTH -> content.length.toString, HeaderNames.CONTENT_TYPE -> contentType) ++ filename.map { fn => Map(HeaderNames.CONTENT_DISPOSITION -> ("""attachment; filename="%s"""".format(fn))) }.getOrElse(Map.empty)) SimpleResult(newHeader, Enumerator(content)) } } }
こう書くと、
object Application extends Controller { object DataStore { val filename = "hoge.gif" val contentType = "image/gif" val blobdata = "data".getBytes } def index = Action { request => Ok.withByteContent(DataStore.contentType, Some(DataStore.filename), DataStore.blobdata) } }
こんな感じで書けるようになります。implicit classすげー。
Githubにも置いておきます。
https://github.com/jetBeaver/ByteContentResult