在 Play 中路由到静态文件! 2.0
Posted
技术标签:
【中文标题】在 Play 中路由到静态文件! 2.0【英文标题】:Route to static file in Play! 2.0 【发布时间】:2012-04-05 06:41:10 【问题描述】:我正在尝试创建到特定静态文件的路由,但我尝试的所有操作都以错误结束。
我做了 3 次不同的尝试:
1.
GET /file staticFile:/public/html/file.html
我得到的错误:
Compilation error
string matching regex `\z' expected but `:' found
2.
GET /file controllers.Assets.at(path="/public/html", "file.html")
我得到的错误:
Compilation error
Identifier expected
3.
GET /file controllers.Assets.at(path="/public/html", file="file.html")
我得到的错误:(这是最奇怪的)
Compilation error
not enough arguments for method at: (path: String, file: String)play.api.mvc.Call. Unspecified value parameter file.
关于第 3 个错误的奇怪之处在于,它在以下行的不同文件 (app/views/main.scala.html) 中抛出:
<link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">
所有这些方法都可以在 *** 上的官方文档和/或线程中找到。 我在这里错过了什么?
谢谢。
【问题讨论】:
我认为第三个错误发生在默认模板中提到公共路由的第一个实例的地方。我有完全相同的问题。我希望你/我尝试添加的静态链接会弄乱反向路由。 什么?两年,没有公认的答案。这个问题解决了吗? @Jus12 对不起,只是我没有继续玩游戏(不是我的选择,很不幸),我不知道哪个答案是正确的。当时得票最多的那个并没有解决这个问题(正如我的评论所解释的那样)。如果有人让我知道任何答案是否正确,我很乐意将其标记为已接受。 @NitzanTomer answer by Michael Allen 为我工作。 @Jus12 因为我不知道该怎么做,所以我在元站点中询问了建议,看起来应该保持原样:meta.***.com/questions/272882/… 【参考方案1】:IIRC,改变
<link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">
到
<link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/", "main.css")">
我说的是你的第三次尝试
另外,注意额外的 /
编辑
GET /assets/main.css controllers.Assets.at(path="/public", file="/stylesheets/main.css")
假设您的资源位于 /public/stylesheets/main.css
【讨论】:
这只是解决了另一个错误,但是您更改的不是问题,当我注释掉此路由行时一切正常(除了文件未提供)。第三次尝试的错误是主模板文件,这正是我从 play new app-name 命令得到的,我没有更改它,正如我所写的,它在没有那个路由。【参考方案2】:我在尝试配置一些额外的 CSS 时遇到了同样的问题。它在“路由”文件中使用此语法
GET /css/*file controllers.Assets.at(path="/public/css", file)
【讨论】:
同上一个,它有效,但我们似乎不知道为什么【参考方案3】:我有完全相同的问题。我遵循了@Jamil 的建议,并设法让它适用于静态文件(在我的情况下是一个 favicon),并设法让模板编译,但在尝试使用视图时在运行时出现新错误。相关代码如下,
更改路线(此路线现在可以正确解析)
GET /favicon.ico controllers.Assets.at(path="/public/images", file="favicon.png")
更改视图(编译)
<link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/","main.css")">
新错误(仅在运行时)
[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))
我知道这不是一个答案,但也许它会让某人想出一个答案。
【讨论】:
感谢您的回复,到目前为止我还没有尝试过,希望能够回复并报告。 正确的路径是这样的:"GET /favicon.ico controllers.Assets.at(path="/public", file="images/favicon.ico")"【参考方案4】:我不完全确定这是否正确,但这是我们用来映射包含我们的图像、javascripts 等的公共文件夹的方法。
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.at(path="/public", file)
【讨论】:
感谢您的回复,到目前为止我还没有尝试过,希望能够回复并报告。 如果我将“public”文件夹重命名为“assets”,这似乎不起作用(使用path="/assets"
,...)。知道为什么吗?【参考方案5】:
据我所知,这个能力还没有被添加。但是如果有人需要回答,作为一种选择,可以为此目的创建辅助控制器:
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
然后在路由配置中
GET / controllers.StaticFile.html(file = "public/index.html")
【讨论】:
【参考方案6】:我遇到了同样的问题。当我将第二个controllers.Assets.at
添加到类似
GET /assets/*file controllers.Assets.at(path="/public", file)
GET /assets2/*file controllers.Assets.at(path="/public2", file)
main.scala.html 中默认的@routes.Assets.at
调用编译失败
Compilation error
not enough arguments for method at: (path: String, file: String)play.api.mvc.Call. Unspecified value parameter file.
这似乎是因为有多个匹配对象的隐式参数。解决方法是添加一个前导位置参数:
href="@routes.Assets.at("/public","/css/main.css")"
不幸的是,如果您回到路由中只有一个资产行,您将不得不更改为单参数形式以避免编译错误。对我来说似乎是一个错误。
【讨论】:
【参考方案7】:最干净的解决方案是创建您自己的 AssetsBuilder 来构建您的静态页面。
在你的控制器包中创建这个文件 - Static.scala
package controllers
object Static extends AssetsBuilder
然后在你的路由中你可以定义你的静态端点
GET /file controllers.Static.at(path="/public/html", "file.html")
完成。现在/public/html/file.html
的文件将由localhost:9000/file
提供
如果您将上面的硬代码替换为更通用的:
GET /*file controllers.Static.at(path="/public/html", *file + ".html")
然后/foo
将服务于/public/html/foo.html
,/bar
将服务于/public/html/bar.html
等等。
【讨论】:
【参考方案8】:您的第三次尝试几乎是正确的。 而不是
GET /file controllers.Assets.at(path="/public/html", file="file.html")
这样做
GET /file controllers.Assets.at(path="/public", file="html/file.html")
我之前也遇到过同样的问题。我的路由文件是这样的。
# 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)
我在视图内有以下反向路线 (examples.scala.html
)
@routes.Assets.at("imagefolder") #try to generate path to /public/imagefolder.
当我打开http://localhost:9000/exmpl
时,出现了这个错误。
not enough arguments for method at: (path: String, file: String)play.api.mvc.Call. Unspecified value parameter file.
为了解决这个问题,我只是改变了这条路线
GET / controllers.Assets.at(path="/public/html", file="static.html")
到这里
GET / controllers.Assets.at(path="/public", file="html/static.html")
这个解决方案对我有用。我希望它也适用于你和其他人。
【讨论】:
【参考方案9】:在 jar 文件中播放 java 包公用文件夹,如果您想提供解析为服务器中绝对文件位置的静态文件,这将是一个问题。正确的做法是拥有自己的控制器并使用它来提供静态文件。
例如,提供位于
中的文件“mystatic.html”<your playhome>
|-----<myfolder>
|------mystatic.html
您可以在您的路由文件中配置此路由。
GET /mystatic mypackage.mycontrollers.Static.getFile(path="/myfolder/mystatic.html")
您的控制器将按如下方式实现。
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();
【讨论】:
以上是关于在 Play 中路由到静态文件! 2.0的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Play 的静态方法中使用 play.cache.CacheApi!框架 2.4.2
如何从 Play 框架中的 YAML 固定装置加载(静态嵌套)枚举值?
Qt5.2.0 MinGW480 release静态版编译结果过程及QtCreator配置分享(realfan的编译方法)(configure -h可以显示帮助)(静态编译mysql插件,需要做一些