Search code examples
scalaplayframeworkplayframework-2.5

unable to locate files with play framework sendFile function


The goal is to be able to both download and render (e.g. profile pic) images that are either a public asset or a private one.

In the Play Framework docs (ScalaStream), it says:

Play provides easy-to-use helpers for common task of serving a local file:

def index = Action {
  Ok.sendFile(new java.io.File("/tmp/fileToServe.pdf"))
}

If you want to serve this file inline:

def index = Action {
  Ok.sendFile(
    content = new java.io.File("/tmp/fileToServe.pdf"),
    inline = true
  )
}

This looks like what is needed to achieve the goal.

Now, I have a directory structure as shown below, and would like to serve the files 1.png and 2.png

MyApp
|_ app
|_ conf
|_ public (all public assets)
   |_ images
      |_ 1.png
|_ private (more assets, not public)
   |_ images
      |_ 2.png
|_ ...

I have defined a controller function as follows:

def sendImage() = Action {
  // Ok.sendFile(new java.io.File("/public/images/1.png"))
  // Ok.sendFile(new java.io.File("assets/images/1.png"))
  Ok.sendFile(new java.io.File("/private/images/1.png"))
}

Tried various different paths, absolute, relative, but when I call this controller function from the front-end (React / Axios), it only returns "NoSuchFileException".

However, I am able to render public assets from the front-end simply using:

<img src='/assets/images/1.png' />   // from the public dir

The same path does not work from within the controller. Could not figure out how Play expects its paths.

Currently using Play 2.5

Any ideas? Thanks


Solution

  • The comment by @marcospereira is what helped resolve the path, thanks!

    When you use / before the file name, this expects the full path of the file and not a relative one. You need to change from /private/images/1.png to private/images/1.png so that it will be relative to your application.

    But, if these private files are uploaded by the user, have them inside the application directory would be considered a bad practice. What will happen when you deploy a new version of the application? You will either lose the files or you will need to copy/move them while deploying. So, have an directory that is external to the application to store uploaded files.