Play Framework:在PRODUCTION模式下处理动态创建的文件(图像)

时间:2015-08-25 13:51:07

标签: image scala playframework playframework-2.2 playframework-2.3

我试图允许用户将照片上传到服务器,然后在生产(非开发)中查看它们(所有用户都可以查看所有照片)。在开发模式中,一切都很简单 - 我可以将文件上传到公共文件夹,然后从那里读取,在生产模式我无法访问公共文件夹了(因为这种方法适用于静态访问而非动态)。

所以,我有两个问题:

  1. 上传:目前我无法理解如何将上传的照片保存到特定文件夹,而不使用我想要保存照片的位置的绝对路径。
  2. 以下是上传代码(与本指南类似 - https://www.playframework.com/documentation/2.4.x/ScalaFileUpload):

    def uploadPhoto = Action(parse.multipartFormData) { request =>
      import play.api.mvc.MultipartFormData
      import play.api.libs.Files.TemporaryFile
      import java.io.File
      import java.nio.file.Path
      import java.nio.file.Paths
    
      try {
        val multipartForm: MultipartFormData[TemporaryFile] = request.body
    
        val pathDev: Path = Paths.get("./public/img");
        val pathProduction: Path = Paths.get("/...<[full path]>.../public/img");
        val imgPath =
          if (Files.exists(pathDev)) { pathDev.toString() } 
          else { pathProduction.toString() }
    
        val newFile = img.get.ref.moveTo(new File(s"$imgPath/$imgName"))
        // [HERE I save the path to my DB]
        Ok(Json.obj("imgName" -> imgName))
    
      } catch {
        case e: Exception =>
          BadRequest("unknown error")
      }
    }
    
    1. 我不清楚如何将上传的图片提供给用户以便查看它们。 我想动态更改img html标签中的scr以显示相关图像,如下所示:$(&#34;#img&#34;)。attr(&#34; src&#34;,&#39; assets /img/1.jpg');
    2. 但由于公共文件夹不可用,图像是&#34;不存在&#34; (至少直到我将&#34;阶段&#34;项目并重新运行它 - https://www.playframework.com/documentation/2.4.x/Assets)。

      我尝试了以下方法(https://www.playframework.com/documentation/2.4.x/ScalaStream): 我已将以下行添加到我的conf / routes文件中: GET / img /:filename controllers.MyController.getPhoto(filename)

      并在控制器中定义了以下函数:     def getPhoto(filename:String)= Action {       Ok.sendFile(新的java.io.File(&#34; ./ img /&#34; + filename))     }

      但是浏览器正在下载文件而不是显示它......

      这些是相关的: Handling dynamic created files in play 2 How to serve uploaded files in Play!2 using Scala?

      任何援助都将被非常挪用。

2 个答案:

答案 0 :(得分:2)

以下是我如何解决此问题

问题1

对于上传文件路径,在游戏中你可以在conf / application.conf文件中定义配置,你可以使用不同的文件进行生产模式,使用-Dconfig.file = / path / to / the / file。

所以我定义了一个名为myapp.image.base的属性,在调试模式下只需将其设置为&#34;&#34;,并在生产模式下(我创建了一个名为conf / application.prod.conf的文件),我把它放在绝对的路径上。 所以在我的代码中,我总是使用以下命令来获取文件路径(它在Java中,但你应该在Scala中找到类似的方式来读取配置)

Play.application().configuration().getString("myapp.image.base")+"img" 

问题2

用于提供图像 您需要创建一个路由器。 首先在路线文件中添加如下内容:

GET /user/images/:name controllers.Application.imageAt(name:String)

在动作imageAt中编写一个简单的文件阅读器,它以流的形式返回文件。我的示例再次使用Java,但您应该使用Scala将其存档

    File imageFile = new File(ReportFileHelper.getImagePath());
    if (imageFile.exists()) {
    //resource type such as image+png, image+jpg
        String resourceType = "image+"+imageName.substring(imageName.length()-3);
        return ok(new FileInputStream(imageFile)).as(resourceType);
    } else {
        return notFound(imageFile.getAbsoluteFile());
    }

之后,可以从url / user / images /

访问图像

答案 1 :(得分:1)

Play从类路径(包括assets目录)中读取文件。在JVM上,类路径是不可变的 - 一旦启动,添加到类路径上的文件夹的文件实际上不会被添加到类路径中。

这适用于开发模式,因为Play会在检测到更改时重新加载类路径。生产中没有启用相同的热重装(有充分理由)。