Reading Files from public folder in play framework in production
Asked Answered
A

5

10

My play app is in 2.4.2. In Developer Mode,I used to read files from public folder at back-end controllers using Source.fromFile("./public/files/abc.json")

When I converted the application to production mode, I am getting File Not Found Exceptions. I found that the public folder is packed in an assets jar in production mode.What can i do so that it works in both development and production mode??

Acknowledgment answered 28/4, 2016 at 5:38 Comment(2)
You could try reading it from the classpath: https://mcmap.net/q/46334/-how-to-read-text-file-from-classpath-in-javaFibre
@user1869107 " In Production mode,Play's class loader can read files only from conf folder" -> This is not correct. Actually you can add other resource directories to the Play framework in distribution. I will edit my answer and add how.Saccular
S
7

Have you tried out this Play Documentation https://www.playframework.com/documentation/2.5.x/AssetsOverview ? This is Ok with Play 2.4 and even with 2.3 also, I have tried out.

In there you can find this, you can simply do this in your conf/routes file.

GET  /assets/*file        controllers.Assets.at(path="/public", file)

file -> refers to the file name. Ex: myFile.json

To make this work in production mode you have to do some little more work. As explained in this answer, add these lines into your /build.sbt file.

import com.typesafe.sbt.packager.MappingsHelper._
    mappings in Universal ++= directory(baseDirectory.value / "public")

That would include your 'public' directory inside the dist file (You can include any directory like that way). Then your application would work in the production environment.

Saccular answered 12/5, 2016 at 7:51 Comment(1)
The sbt directives given here also work for Play 2.3!Sporogonium
A
4

You can use this method:

Play.application().getFile("/public/foobar.baz");

Method Doc:

Get a file relative to the application root path.

Amphiboly answered 29/4, 2016 at 13:21 Comment(1)
this was helpful because it pointed me to the resourceAsStream methodSporogonium
R
1

Use Source.fromResource instead of Source.fromFile if you are using scala 2.12.

Example:

If you put the file in public folder, don't use the leading slash.

Source.fromResource(“public/files/abc.txt”)

If you put the file in conf folder, don't include conf in the path.

Source.fromResource(“files/abc.txt”)  // conf/files/abc.txt

If you are using scala < 2.12, you can fall back to Java. There are 2 ways.

Relative path(no leading slash)

scala.io.Source.fromInputStream(getClass.getClassLoader.getResourceAsStream(“public/test.txt”))

Absolute path (leading slash required)

scala.io.Source.fromInputStream(getClass.getResourceAsStream(“/public/test.txt”))

I guess you also have to exclude "conf" in the path if you put the file in conf folder.

Lastly, you can learn how Java's resource loading works in this blog.

Reprise answered 19/4, 2019 at 7:46 Comment(0)
R
0

Play comes with a built-in controller to serve public assets.

The controller is available in the default Play JAR as controllers.Assets and defines a single at action with two parameters:

Assets.at(path: String, file: String) The path parameter must be fixed and defines the directory managed by the action. The file parameter is usually dynamically extracted from the request path.

Here is the typical mapping of the Assets controller in your conf/routes file:

GET  /assets/*file        controllers.Assets.at(path="/public", file)

Refer here for more.

Rackrent answered 13/5, 2016 at 14:41 Comment(0)
A
0

There are two ways to resolve this:- 1) Straight one is to use what Supun Wijerathne suggested in the comment above. 2) Second one is to use the following approach, if one does not want to add an extra public folder in the distribution version of the application:- a) Copy all files from public folder in conf folder. b) Get resource as stream using Play's classloader. c) Convert this inputstream to bufferedsource using Source.fromInputStream method. Now, this file can be used by the controller for processing.

Acknowledgment answered 15/7, 2016 at 10:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.