仅为图像覆盖ASP.NET代字号(〜)分辨率

时间:2012-04-25 11:54:17

标签: asp.net cdn virtualpathprovider resolveurl

我有一个大型遗留应用程序,我想将所有图像移动到CDN。

目前,我们所有的图像都位于应用程序根目录下,因此路径都像"~/Images/MyImage.jpg."。由于我们系统的要求,我必须在运行时确定给定图像的完整URL(如果是住在CDN。这使我们可以严格控制版本控制,缓存等。逐个图像地进行代码更改将是一个非常漫长,乏味且容易出错的过程。

我想要做的是能够在ASP.NET中使用某种机制,我可以决定如何解析图像的波形符。这将允许我们现有的所有代码保持原样,并且图像将在运行时定向到CDN。

我发现了 VirtualPathProviders 的一些提及,听起来可能就是我想要的,但当我测试它时,唯一的路径被传递到 CombineVirtualPaths function是以.ASPX, .ASCX, and .MASTER结尾的路径。

任何人都可以帮我找到一个干净,低风险的选择吗?

基本上,我需要的是在我的应用程序的任何地方,我将“〜/ images / myimage.jpg”呈现给浏览器“http://mycdnhost.com/myimage.jpg”。这样可以避免浏览器向我们的服务器发送图像请求。

1 个答案:

答案 0 :(得分:3)

使用IIS路由

从其他站点或服务器提供静态内容。 您的Web应用程序部署在多个服务器上,动态Web内容位于一个站点或服务器上,所有静态内容位于不同的站点或服务器上。您可以使用URL重写模块和IIS应用程序请求路由模块将所有静态文件请求转发到其他服务器,同时为当前服务器的所有动态Web页面请求提供服务。这样,ASP.NET路由仅用于动态Web内容,不会评估静态内容的任何URL。

以下示例显示了可用于此方案的URL重写规则:

<rewrite>
    <rules>
        <rule name="Forward to static file server">
            <match url="^.+\.(?:jpg|bmp|gif)$" />
            <action type="Rewrite" url="http://static_file_server/{R:0}" />
        </rule>
    </rules>
</rewrite>

更多信息:http://learn.iis.net/page.aspx/496/iis-url-rewriting-and-aspnet-routing/

使用HttpModule

  1. 您应该尝试创建拦截图像请求的HttpModule,并尝试将它们重定向到您的CDN路径。首先,您需要将映像文件的文件扩展名映射到IIS中的aspnet_isapi。 然后,添加一个httpmodule,对这些文件扩展名执行url重定向。 例如,在模块的beginrequest方法中:

    void context_BeginRequest(object sender,EventArgs e) { if(request.url.endwith .jpg / .png ...)    重定向到相对于根文件夹的路径。 }

  2. 使用httpmodule的另一个选项是截取html渲染并使用正则表达式替换图像URL以指向CDN。在这里你可以看到它是如何工作的http://shoaibsheikh.blogspot.com/2012/05/change-image-url-in-aspnet-using.html

  3. 这种方法会增加asp.net生命周期的开销,因为我们必须在将整个页面发送到客户端之前拦截它。

    使用控制适配器

    如果您只想处理劫持图像控制渲染方法的图像控件并选择性地将路径更改为cdn url,则应尝试使用ASP.Net控制适配器。这种方法风险较小,可拆卸。

     public class CDNImageControlAdapter : ControlAdapter
        {
            protected override void Render(HtmlTextWriter writer)
            {
                Image img = this.Control as Image;
                if (img == null)
                {
                    base.Render(writer);
                    return;
                }
    
                if (img.ImageUrl.Length > 0)
                {
                    // Let the HyperLink render its begin tag
                    img.RenderBeginTag(writer);
    
                    Image image = new Image();
    
                    if (img.ImageUrl.IndexOf("~") == 0)
                    {
                        img.ImageUrl = (img.ImageUrl.Replace("~", "http://mycdn.com/images/"));
    
                    }
    
                    img.RenderControl(writer);
                }
                else
                {
                    // HyperLink.RenderContents handles a couple of other
                    // cases if its ImageUrl property hasn't been set. We
                    // delegate to that behavior here.
                    base.Render(writer);
                }
            }
        }
    

    并在App_Browsers应用程序文件夹中添加All.broswer文件

    <!--
        You can find existing browser definitions at
        <windir>\Microsoft.NET\Framework\<ver>\CONFIG\Browsers
    -->
    <browsers>
      <browser id="Default">
        <controlAdapters>
          <adapter controlType="System.Web.UI.WebControls.Image" adapterType="CDNImageControlAdapter, MyWebApplication" />
        </controlAdapters>
      </browser>
    </browsers>
    

    问候。