代码之家  ›  专栏  ›  技术社区  ›  Martin Liversage

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

  •  65
  • Martin Liversage  · 技术社区  · 15 年前

    ASP.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 . 然后我想为静态文件创建一个处理程序。ASP.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);
    

    但是使用内部类型似乎不是正确的解决方案。另一个选择是实现我自己的 静态文件处理程序 但是正确地这样做(支持诸如range和etags之类的HTTP内容)是非常重要的。

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

    5 回复  |  直到 8 年前
        1
  •  41
  •   Benj Sanders    8 年前

    在深入研究这个问题几个小时后,我发现简单地添加忽略规则就可以为静态文件提供服务。

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

    routes.IgnoreRoute("{file}.js");
    routes.IgnoreRoute("{file}.html");
    
        2
  •  50
  •   Dan Atkinson    8 年前

    为什么不使用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>
    

    为@Ryandawkins编辑2015-06-17 :

    如果你想知道重写规则在哪里,这是它在 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>
    
        3
  •  9
  •   sheikhomar    14 年前

    我也遇到过类似的问题。我最后用了 HttpContext.RewritePath :

    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));
            }
        }
    }
    
        4
  •  6
  •   Martin Liversage    15 年前

    我想出了一个替代使用内部 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.
      }
    
    }
    

    这是一个黑客。这个 伊鲁特汉德勒 应该返回一个 IHttpHandler 不中止和传输当前请求。然而,它确实实现了我想要的。

    使用内部 静态文件处理程序 也有点像黑客,因为我需要思考才能访问它,但至少有一些 documentation on StaticFileHandler on MSDN 使它稍微更“正式”一点。不幸的是,我认为在部分信任环境中不可能考虑内部类。

    我会坚持用 静态文件处理程序 因为我认为在可预见的将来它不会从ASP.NET中删除。

        5
  •  3
  •   Community Egal    7 年前

    您需要添加TransferRequestHandler来处理静态文件。请参阅以下答案 https://stackoverflow.com/a/21724783/22858