2010-03-27 97 views
2

我在移动所有的图像在我的web应用程序转移到CDN的过程图像,但我希望能够轻松地切换CDN或关闭,而不必硬编码路径到图像。CDN在ASP.NET

我首先想到的是添加一个HttpHandler的是,根据在web.config变量(类似)是否会从服务器或从CDN服务图像的图像扩展。但尽管如此,我认为我基本上排除了这一点,因为它会导致ASP.NET处理每个映像的请求,从而增加开销,并且可能实际上完全减轻了使用CDN的好处。

另一种方法是,因为我所有的页面从基本页类继承,我可以创建基类,它决定了路径为来自基于关闭的web.config变量文件的功能。然后我会做这样的事在标记:

<img src='<%= GetImagePath()/image.png' /> 

我想,这大概就是我将不得不最终做,但似乎有点麻烦我。由于“<%=”,虽然“<%#”解决方案可能可行,但我还想象出旧的.NET错误无法修改控制集合。

关于如何实现这个的任何想法或想法?

回答

0

你可以循环所有的控制和更改预渲染事件的图片网址,您的基类...

2

您已经驳回编写基于预先优化的假设的HttpHandler。我会重新考虑这个,并且写一个简单的HttpHandler并测试一下。您可能会发现您的Page方法解决方案可能会更慢,特别是如果您涉及ASP预处理器。

HttpHandlers的是相当接近的金属 - 这是开销IIS手请求ASP.Net的量微乎其微。这将是比您提出的更优雅的解决方案,并且可能更具可扩展性,我愿意下注 - 速度更快。

+0

是啊,我不知道为什么我甚至没有意识到第二个方法介入的ASP.net过程。 。 。对我而言,这是非常不体面的。我想我最大的担忧是,每个图像请求会从CDN请求图像,并可能缓解来自CDN的响应头完成的客户端缓存?我不知道发生了什么事情可以做出决定。 – Chris 2010-03-27 20:21:18

+0

如果您的HttpHandler的服务器上的图像数据,那么你不使用的CDN得到任何节省带宽。另一个选择是让你的HttpHandler发送一个302到相同URL的CDN版本。 – David 2011-05-25 22:04:05

0

有关HTTP处理程序方法的好处是,它很可重复使用和可配置:您可以根据位置确定IMG路径,以处理 - 假设他们在帮助这是结构。

的可能的缺点是图像文件的扩展(.JPG,.PNG等)不到asp.net管线自动传递;你可以很容易地配置IIS来做到这一点 - 但你需要在IIS上有一定的控制级别 - 所以如果你在共享主机环境中,它可能不是一个选项。

2

你有没有考虑过一个更简单的方法?

如果您的页面都是从基类继承的,那么您可以在其中包含CDN的前缀URL的属性(或者如果您要关闭CDN,则将其包含到本地服务器)。然后将预先安装的URL存储在网络中是一件微不足道的事情。配置:

public string PrependURLPath() { 
get { return ConfigurationManager.AppSettings["ImagePrependURL"].ToString(); } 
} 

在你<appSettings/>元素,你可以简单地选择前置网址是什么,例如:

http://my.cdn.com/user/

或:

http://my.own.server.com/images/ 

很简单!

然后,您就能够将您的图像refernces按您的示例代码,但调用你的基本页面属性暴露所需的路径:

<img src='<%= this.BasePage.PrependURLPath() + [YourImagePath.png] %>'/> 

我同意,通过内嵌的呼叫设置图像源凌乱,但你可以像别人建议的那样做,然后遍历页面上的图像控件,并随时更改预定义URL。

即使您的页面当前仅从System.Web.UI.Page继承,创建您自己的基类继承System.Web.Page,然后在解决方案中查找/替换剩余的所有元素页面。

希望这会有所帮助。

1

如果显示使用标签,你可以创建一个控制适配器您的图像,这些让你改变的方式.NET控件呈现或普遍改变他们这样的事情应该做的伎俩:

using System.Web.UI.WebControls.Adapters; 
using System.Web.UI; 
using System.Web.UI.WebControls; 

namespace ExampleCode 
{ 
    public class ImageAdapter : WebControlAdapter 
    { 
     private bool UseCdn 
     { 
      get { return true; } // Get value from config or anywhere else 
     } 

     protected override void OnPreRender(EventArgs e) 
     { 
      base.OnPreRender(e); 

      Image image = (Image)Control; 

      if (UseCdn) 
      { 
       // If using relative urls for images may need to handle ~ 
       image.ImageUrl = String.Format("{0}/{1}", "CDN URL", image.ImageUrl); 
      } 
     } 
     } 
} 

然后加入浏览器文件到文件夹App_Browsers文件在Web项目如下图所示:

<browsers> 
    <browser refID="Default"> 
     <controlAdapters> 
     <adapter 
      controlType="System.Web.UI.WebControls.Image" 
      adapterType="ExampleCode.ImageAdapter" 
      /> 
     </controlAdapters> 
    </browser> 
</browsers> 
0

我会去为图像控制@Rhys方法。

大部分时间,我尝试使用背景图像CSS比使用图像控制。

之后,我将css和图像一起上载到云中,并且相对路径正常工作。

2

在这里很晚很重,但我一直在寻找类似的解决方案。谷歌搜查完善检查我做了什么。没有考虑HttpHandler办法,我就是这样做无非是延长ASP.net Image控制:

public class Img : Image 
{ 
    public Img() 
    { 
     RelativePath = false; 
    } 

    public bool RelativePath { get; set; } 

    public override string ImageUrl 
    { 
     get 
     { 
      if (RelativePath) 
       return base.ImageUrl; 

      return "http://some.configurable-value.com" + base.ImageUrl; 
     } 
     set { base.ImageUrl = value; } 
    } 
} 

它的粗糙,并准备好了,但它的工作原理:)显然应该依靠一些配置的值,而不是字符串字面意思,但这不是一个大变化

0

看起来好像还没有被接受的答案,所以这里是我的建议。我有类似的问题处理URL的透明(不同的一端,但我也考虑过将它用于CDN支持)。

这是一个古老的过滤器/模块,但它运作良好,我需要一点点调整:http://www.paraesthesia.com/archive/2007/12/14/urlabsolutifiermodule---convert-urls-in-asp.net-output-to-absolute.aspx

你可以做的是使一个响应滤波器,并用HTTP模块(如本absolutifier一样)把它捞起来。如果你使用这个模块+响应滤波器,你也许可以做到,你需要通过修改它的源代码来代替主机名/前缀的所有URL使用CDN的内容。

0

我不得不解决您的问题,另外一个,那就是我不希望在开发过程中,但只有当网站被部署在生产服务器上采取从CDN资源。 为了解决这个我开发了预先将CDN URL只在生产中的ExpressionBuilder。

<asp:Image ImageUrl="<%$ CdnUrl:/images/myimage.png %>" runat="server" /> 

在前面的代码中,CDN URL将仅在生产中预先生成。

namespace IdeaR.Web.Compilation 
{ 
[ExpressionPrefix("CdnUrl")] 
public class CdnUrlExpressionBuilder : ExpressionBuilder 
{ 
    public static object GetCdnUrl(string expression, Type target, string entry) 
    { 
     var retvalue = expression; 
     var productionUri = new Uri("http://www.myproductionurl.com", 
      UriKind.Absolute); 
     var currentUri = HttpContext.Current.Request.Url; 
     var cdnUrl = "http://cdn.mycdn.com"; 

     // If this is a production website URL 
     if (currentUri.Scheme == productionUri.Scheme && 
      currentUri.Host == productionUri.Host) 
      retvalue = cdnUrl + expression; 

     return retvalue; 
    } 

    public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, 
     object parsedData, ExpressionBuilderContext context) 
    { 
     var componentType = entry.DeclaringType; 
     var expressionArray = new CodeExpression[3] 
     { 
      new CodePrimitiveExpression(entry.Expression.Trim()), 
      new CodeTypeOfExpression(componentType), 
      new CodePrimitiveExpression(entry.Name) 
     }; 

     var descriptor = TypeDescriptor.GetProperties(componentType) 
      [entry.PropertyInfo.Name]; 
     return new CodeCastExpression(descriptor.PropertyType, 
      new CodeMethodInvokeExpression(
       new CodeTypeReferenceExpression(GetType()), 
       "GetCdnUrl", expressionArray)); 
    }  
} 
} 

欲了解更多信息,我写了一篇文章对这个 How to use a CDN in production but not during development