8

我需要为我网站上的所有图像使用 CDN。所以,我决定使用 IIS Url 重写模块,因为手动编辑我所有的站点视图——这对我来说是不可能的。

所以我为 IIS 制定了规则,例如:

<rule name="cdn1" stopProcessing="true">

   <match url="^Content/Images.*/(.*\.(png|jpeg|jpg|gif))$" />

   <action 
      type="Redirect" 
      url="http://c200001.r9.cf1.rackcdn.com/{ToLower:{R:1}}" 
      redirectType="Permanent" />

</rule>

它有效,但正如您所见,使用了重定向类型(301 Permanent)。而且我认为它会影响网站性能。也许可以编辑Request.Output来替换图像 URL?

请建议,我如何使用 CDN 处理图像,不要编辑我的视图并避免重定向?

任何帮助将不胜感激

4

2 回答 2

7

我同意史蒂夫。您让 URL 重写器执行 301 重定向,但是对于页面需要的每个图像,浏览器仍然首先向服务器发出请求,以发现它是 301 重定向到 CDN Url。此时您唯一要保存的是下载内容。

而不是这样做,您可以只放置一个响应过滤器,该过滤器将在响应发送到客户端浏览器之前修改资产的 URL。这样,客户端浏览器就不必对您的服务器进行任何调用以获取静态资产:

protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
    filterContext.RequestContext.HttpContext.Response.Filter = new CdnResponseFilter(filterContext.RequestContext.HttpContext.Response.Filter);
}

然后是 CdnResponseFilter:

public class CdnResponseFilter : MemoryStream
{
    private Stream Stream { get; set; }

    public CdnResponseFilter(Stream stream)
    {
        Stream = stream;
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        var data = new byte[count];
        Buffer.BlockCopy(buffer, offset, data, 0, count);
        string html = Encoding.Default.GetString(buffer);

        html = Regex.Replace(html, "src=\"/Content/([^\"]+)\"", FixUrl, RegexOptions.IgnoreCase);
        html = Regex.Replace(html, "href=\"/Content/([^\"]+)\"", FixUrl, RegexOptions.IgnoreCase);              

        byte[] outData = Encoding.Default.GetBytes(html);
        Stream.Write(outData, 0, outData.GetLength(0));
    }

    private static string FixUrl(Match match)
    {
        //However the Url should be replaced
    }
}

这样做的结果是所有看起来像的内容资产<img src="\Content\whatever.jpg" />都将转换为<img src="cdn-url.com\Content\whatever.jpg" />

于 2011-07-31T22:37:04.170 回答
1

鉴于原始 URL 来自您的内容,而不是例如来自书签,我认为您将难以避免对您的网站的请求和重定向;潜在的重大性能影响,可能会抵消使用 CDN 的好处。

如果您可以对传输到浏览器的 HTML 应用 URL 重写,而不是在请求到来时进行,那会更好。

麻烦的是,我不知道怎么做(除非你使用的是 ISA 服务器,在这种情况下我可以告诉你,但我怀疑你不是)!

您可以创建一个自定义 ActionFilter 并覆盖 OnResultExecuted,但您需要使用 filter 属性注释您的控制器。

于 2011-07-31T22:12:19.453 回答