Liftことはじめ その3 ファイルダウンロード

前述の記事の覚え書き

ファイルダウンロード
snippet/TrackView.scala

  private def doList(reDraw: () => JsCmd)(html: NodeSeq): NodeSeq = {
    val tracks:List[Track] = Track.findAll(By(Track.albumid, getAlbumId().toLong), OrderBy(Track.seq, Ascending))
    bind("track", html, "albumid" -> <input type="text" name="albumid" class="column span-10"/>)
    tracks.flatMap(trk =>
      bind("track", html, AttrBindParam("id", trk.id.toString, "id"),
                          "seq" -> <span>{link("track?albumid=" + getAlbumId() + "&seq=" +trk.seq.get, () => (), Text(trk.seq.toString))}</span>,
                          "tracktitle" -> <span>{trk.tracktitle.toString}</span>,
                          "filename" -> <span>{link("lob/" + trk.id.get.toString, () => (), Text(trk.filename.toString))}</span>,
                          "delete" -> <span>{link("track?albumid=" + getAlbumId(), () => delete(trk.id.get), Text("delete"))}</span>
      )
    )
  }

filenameに、パス /lobを定義。

scala/bootstrap/liftweb/Boot.scala

class Boot {
  def boot {
…
    // Download url
    import code.lib._
    LiftRules.statelessDispatchTable.append{
      case Req( "lob" :: id :: Nil, _, _ ) =>
        () => TrackDownload.download(id.toLong)
    }

idを引数とするdownloadメソッドを定義。

lib/TrackDownload.scala

package code.lib

import java.io._
import javax.mail.internet._
import net.liftweb.common._

import code.model.Track
import net.liftweb.mapper._
import net.liftweb.http._

object TrackDownload {
  def download(id: Long): Box[LiftResponse] = {
    val track: Track = (Track.findAll(By(Track.id, id))).head
    val bais = new ByteArrayInputStream(track.trackatach.get)
    val attachment = "attachment; filename=\'" + MimeUtility.encodeWord(track.filename.get.replace(" ", "_"), "ISO-2022-JP", "B") + "\'"
    val content = track.mimetype.get + "; charset=UTF-8"
    val headers = ("Content-Type" -> content) :: ("Content-length" -> track.trackatach.get.length.toString) ::("Content-disposition" -> attachment) :: Nil
    Full(
      StreamingResponse(bais, () => {bais.close}, track.trackatach.get.length, headers, Nil, 200)
    )
  }
}

lobをByteArrayInputStreamに取り込み、headerをセットし、StreamingResponseにて返却。
ソースコードこちら