使用 ASP.NET 路由服务静态文件

Net 路由(不是 MVC)可以用来服务静态文件吗?

说我想要路线

http://domain.tld/static/picture.jpg

http://domain.tld/a/b/c/picture.jpg

而且我想动态地执行它,因为重写的 URL 是动态计算的。我不能一劳永逸地设置一个静态路由。

无论如何,我可以创建一条这样的路线:

routes.Add(
"StaticRoute", new Route("static/{file}", new FileRouteHandler())
);

FileRouteHandler.ProcessRequest方法中,我可以重写从 /static/picture.jpg/a/b/c/picture.jpg的路径。然后我想为静态文件创建一个处理程序。NET 为此使用 StaticFileHandler。不幸的是,这个类是内部的。我尝试过使用反射创建处理程序,它实际上是有效的:

Assembly assembly = Assembly.GetAssembly(typeof(IHttpHandler));
Type staticFileHandlerType = assembly.GetType("System.Web.StaticFileHandler");
ConstructorInfo constructorInfo = staticFileHandlerType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null);
return (IHttpHandler) constructorInfo.Invoke(null);

但使用内部类型似乎不是正确的解决方案。另一个选择是实现我自己的 StaticFileHandler,但是正确地实现它(支持诸如范围和标签之类的 HTTP 内容)是非常重要的。

在 ASP.NET 中如何处理静态文件的路由?

78155 次浏览

为什么不使用 IIS 进行此操作?您可以创建一个重定向规则,在第一个路由到达应用程序之前,将任何请求指向第二个路由。正因为如此,它将是重定向请求的一种更快的方法。

假设您有 IIS7 + ,您将执行类似于..。

<rule name="Redirect Static Images" stopProcessing="true">
<match url="^static/?(.*)$" />
<action type="Redirect" url="/a/b/c/{R:1}" redirectType="Permanent" />
</rule>

或者 ,如果你不需要重定向,就像@ni5ni6建议的那样:

<rule name="Rewrite Static Images" stopProcessing="true">
<match url="^static/?(.*)$" />
<action type="Rewrite" url="/a/b/c/{R:1}" />
</rule>

编辑2015-06-17@RyanDawkins :

如果您想知道重写规则去了哪里,这里是它在 web.config文件中的位置的映射。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<!-- rules go below -->
<rule name="Redirect Static Images" stopProcessing="true">
<match url="^static/?(.*)$" />
<action type="Redirect" url="/a/b/c/{R:1}" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

我想出了一个使用内部 StaticFileHandler的替代方案。在 IRouteHandler中,我称之为 HttpServerUtility.Transfer:

public class FileRouteHandler : IRouteHandler {


public IHttpHandler GetHttpHandler(RequestContext requestContext) {
String fileName = (String) requestContext.RouteData.Values["file"];
// Contrived example of mapping.
String routedPath = String.Format("/a/b/c/{0}", fileName);
HttpContext.Current.Server.Transfer(routedPath);
return null; // Never reached.
}


}

这是黑客行为。IRouteHandler应该返回一个 IHttpHandler,而不是中止和传输当前请求。然而,它实际上达到了我想要的效果。

使用内部的 StaticFileHandler也是一种技巧,因为我需要反射来访问它,但至少有一些 MSDN 上关于 StaticFileHandler的文档使它成为一个稍微“正式”一点的类。不幸的是,我认为不可能在部分信任的环境中反思内部类。

我将坚持使用 StaticFileHandler,因为我认为在可预见的将来它不会从 ASP.NET 中删除。

在仔细研究了这个问题几个小时之后,我发现只需添加忽略规则就可以处理静态文件。

在 RegisterRoutes (RouteCollection 路由)中,添加以下忽略规则:

routes.IgnoreRoute("{file}.js");
routes.IgnoreRoute("{file}.html");

我也遇到过类似的问题,最后我用了 重写路径:

public class MyApplication : HttpApplication
{
private readonly Regex r = new Regex("^/static/(.*)$", RegexOptions.IgnoreCase);


public override void Init()
{
BeginRequest += OnBeginRequest;
}


protected void OnBeginRequest(object sender, EventArgs e)
{
var match = r.Match(Request.Url.AbsolutePath);
if (match.Success)
{
var fileName = match.Groups[1].Value;
Context.RewritePath(string.Format("/a/b/c/{0}", fileName));
}
}
}

您需要添加 TransferRequestHandler 来处理静态文件 Https://stackoverflow.com/a/21724783/22858