4

Play Framework 2 Scalaコントローラーから静的ファイルを提供するための推奨される方法は何ですか?

このファイルは私のアプリケーションにバンドルされているため、ファイルシステムを絶対的にハードコーディングすることはできません/path/to/the/file。その場所は、Playアプリがインストールされている場所によって異なるためです。

ファイルはpublic/dirに配置されますが、app / asset /には配置されません。これは、Playにファイルをコンパイルさせたくないためです。

(単にそのファイルにルートを追加しない理由は、そのファイルにアクセスする前にログインする必要があるためです。そうしないと、役に立ちません。)

これが私がこれまでに行ったことですが、これは私の本番サーバーで壊れます。

object Application ...

  def viewAdminPage = Action ... {
    ... authorization ...
    val adminPageFile = Play.getFile("/public/admin/index.html")
    Ok.sendFile(adminPageFile, inline = true)
  }

そして私のroutesファイルには、次の行があります。

GET /-/admin/ controllers.Application.viewAdminPage

問題は、本番サーバーでこのエラーが発生することです。
FileNotFoundException: app1/public/admin/index.html

提供するファイルを指定するために、Play.getFileandではなく他の方法はありますか?OK.sendFileそれは生産を中断することはありませんか?

(私のアプリはにインストールされ、 (なしで)/some-dir/app1/から開始します—代わりにアプリを開始した場合、おそらくすべてが機能します。しかし、コントローラー内から静的ファイルを提供するために、どのように「すべき」かを知りたいです。 ?アプリケーションをどこから開始したかに関係なく、すべてが本番サーバーでも常に機能するようにします)/some-dir/app1//some-dir/app1/

4

5 に答える 5

3

ストリーミング HTTP 応答のドキュメントを確認する

def index = Action {
  Ok.sendFile(
    content = new java.io.File("/tmp/fileToServe.pdf"),
    fileName = _ => "termsOfService.pdf"
  )
}

認証されたユーザーと認証されていないユーザーの間でダウンロードリンクを共有することを避け、高度なダウンロード統計を作成するために、ランダムな文字列をfileName(ログに記録されたユーザーごとに個別に) に追加することができます。

于 2012-08-13T18:54:36.943 に答える
3

私はこれをしました:(しかし、以下のアップデートを見てください!)

val fileUrl: java.net.URL = this.getClass().getResource("/public/admin/file.html")
val file = new java.io.File(adminPageUrl.toURI())
Ok.sendFile(file, inline = true)

(thisはコントローラーであり、提供されているファイルと同じパッケージに配置されている (そして配置されている必要があります)。)

関連する質問は次のとおりです。Javaで相対パスを使用してリソースを開く

アップデート

URI を介してファイルにアクセスすると、エラーが発生します:IllegalArgumentException: URI is not hierarchicalファイルが JAR 内にある場合、これは Play を次のように実行した場合です:play stageそしてtarget/start.

代わりに、ファイルをストリームとして読み取り、文字列に変換して、その文字列を HTML として送信しました。

val adminPageFileString: String = {
  // In prod builds, the file is embedded in a JAR, and accessing it via
  // an URI causes an IllegalArgumentException: "URI is not hierarchical".
  // So use a stream instead.
  val adminPageStream: java.io.InputStream =
    this.getClass().getResourceAsStream("/public/admin/index.html")
  io.Source.fromInputStream(adminPageStream).mkString("")
}

...

return Ok(adminPageFileString) as HTML
于 2012-08-14T06:00:38.003 に答える
1

これに対する手動のアプローチは次のとおりです。

val url = Play.resource(file)
url.map { url =>
  val stream = url.openStream()
  val length = stream.available 
  val resourceData = Enumerator.fromStream(stream)

  val headers = Map(
        CONTENT_LENGTH -> length.toString,
        CONTENT_TYPE -> MimeTypes.forFileName(file).getOrElse(BINARY),
        CONTENT_DISPOSITION -> s"""attachment; filename="$name"""")

  SimpleResult(
    header = ResponseHeader(OK, headers), 
    body = resourceData)

アセットコントローラーを使用した同等のものは次のとおりです。

val name = "someName.ext"

val response = Assets.at("/public", name)(request)
response
  .withHeaders(CONTENT_DISPOSITION -> s"""attachment; filename="$name"""")
于 2013-06-18T12:34:50.490 に答える
1

String を使用せずに、ファイル コンテンツをストリーミングする別のバリ​​アント:

def myStaticRessource() = Action { implicit request =>

  val contentStream = this.getClass.getResourceAsStream("/public/content.html")

  Ok.chunked(Enumerator.fromStream(contentStream)).as(HTML)

}
于 2015-06-07T06:05:15.397 に答える