可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm trying to make a route to a specific static file but everything I'm trying ends with an error.
I've made 3 different attempts:
1.
GET /file staticFile:/public/html/file.html
The error I get:
Compilation error
string matching regex `\z' expected but `:' found
2.
GET /file controllers.Assets.at(path="/public/html", "file.html")
The error I get:
Compilation error
Identifier expected
3.
GET /file controllers.Assets.at(path="/public/html", file="file.html")
The error I get: (and this is the weirdest)
Compilation error
not enough arguments for method at: (path: String, file: String)play.api.mvc.Call. Unspecified value parameter file.
The weird part about the 3rd error is that it's thrown in a different file (app/views/main.scala.html) on the following line:
<link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">
All of these methods were found in the official documentation and/or threads here on stackoverflow.
What am I missing here?
Thanks.
回答1:
IIRC, change
<link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">
To
<link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/", "main.css")">
I am talking about your third attempt
Also, watch out for extra /
EDIT
GET /assets/main.css controllers.Assets.at(path="/public", file="/stylesheets/main.css")
Assuming your resource is at /public/stylesheets/main.css
回答2:
I am not totally sure if this is correct, but this is what we are using to map a public folder containing our images, javascripts... etc..
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.at(path="/public", file)
回答3:
This ability still haven't been added, as I know. But if someone needs answer, as an option, helper controller can be created for these purpose:
object StaticFile extends Controller {
def html(file: String) = Action {
var f = new File(file)
if (f.exists())
Ok(scala.io.Source.fromFile(f.getCanonicalPath()).mkString).as("text/html");
else
NotFound
}
}
and then in routes config
GET / controllers.StaticFile.html(file = "public/index.html")
回答4:
The solution to this that is cleanest is to create your own AssetsBuilder that will build your static page.
Create this file in your controllers package - Static.scala
package controllers
object Static extends AssetsBuilder
Then in your routes you can define your static endpoint
GET /file controllers.Static.at(path="/public/html", "file.html")
Done. Now the file at /public/html/file.html
will be served off of localhost:9000/file
If you replace the hard code above with a more generic:
GET /*file controllers.Static.at(path="/public/html", *file + ".html")
then /foo
will serve /public/html/foo.html
, /bar
will serve /public/html/bar.html
etc.
回答5:
Your third attempt was almost right.
Instead of
GET /file controllers.Assets.at(path="/public/html", file="file.html")
do it like this
GET /file controllers.Assets.at(path="/public", file="html/file.html")
I got the same issue before. My route file looks like this.
# Application
GET / controllers.Assets.at(path="/public/html", file="static.html")
GET /exmpl controllers.Examples.index
# Resources
GET /assets/*file controllers.Assets.at(path="/public", file)
And I have below reverse route inside views (examples.scala.html
)
@routes.Assets.at("imagefolder") #try to generate path to /public/imagefolder.
When I open http://localhost:9000/exmpl
, this error showed up.
not enough arguments for method at: (path: String, file: String)play.api.mvc.Call. Unspecified value parameter file.
To fix this issue, I just changed this route
GET / controllers.Assets.at(path="/public/html", file="static.html")
to this
GET / controllers.Assets.at(path="/public", file="html/static.html")
This solution was works for me. I hope it works for you and the others too.
回答6:
I have the exact same issue. I followed the advice from @Jamil and managed to get this working for the static file (in my case a favicon) and managed to get the templates to compile but get a new error at runtime when trying to use the view. Relevant code below,
Change to the route (this route now resolves correctly)
GET /favicon.ico controllers.Assets.at(path="/public/images", file="favicon.png")
Change to the view (compiles)
<link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/","main.css")">
New error (only at runtime)
[MatchError: (stylesheets/,main.css) (of class scala.Tuple2)]
// @LINE:29
// @LINE:28
def at(path:String, file:String) = {
(path, file) match {
// @LINE:28
case (path, file) if path == "/public" => Call("GET", "/assets/" + implicitly[PathBindable[String]].unbind("file", file))
I know this isnt an answer but perhaps it will allow someone to pipe up with one.
回答7:
I was experiencing the same issue while I was trying to configure some additional css. It worked with this syntax in the "routes" file
GET /css/*file controllers.Assets.at(path="/public/css", file)
回答8:
I ran into the same issue. When I added a second controllers.Assets.at
to routes like
GET /assets/*file controllers.Assets.at(path="/public", file)
GET /assets2/*file controllers.Assets.at(path="/public2", file)
the default @routes.Assets.at
calls in main.scala.html failed compilation
Compilation error
not enough arguments for method at: (path: String, file: String)play.api.mvc.Call. Unspecified value parameter file.
This would seems to be because of an implicit parameter for which there are multiple matching objects. The solution is to add a leading positional parameter:
href="@routes.Assets.at("/public","/css/main.css")"
Unfortunately, if you go back to having only one assets line in routes, you will have to change to the one-parameter form to avoid a compilation error. Seems like a bug to me.
回答9:
Play java packages public folder in a jar file and this would be a problem if you would like to serve a static file that resolves to an absolute file location in the server. The right way to do is to have your own controller and use it to serve the static file.
For ex, to serve a file "mystatic.html" that is in the
<your playhome>
|-----<myfolder>
|------mystatic.html
You would configure this route in your routes file.
GET /mystatic mypackage.mycontrollers.Static.getFile(path="/myfolder/mystatic.html")
and your controller would be implemented as follows.
package mypackage.mycontroller;
import java.io.File;
import com.google.inject.Inject;
import com.google.inject.Provider;
import play.Application;
import play.mvc.Controller;
import play.mvc.Result;
import play.mvc.Results;
public class Static extends Controller {
@Inject
Provider<Application> app;
public Result getFile(String path){
File file = app.get().getFile(path);
if(file.exists()){
return ok(file);
}else{
return Results.notFound();
}
}
}