【问题标题】:Cache images provided through script缓存通过脚本提供的图像
【发布时间】:2011-02-22 17:01:45
【问题描述】:

我有一个脚本,它通过使用几个查询字符串变量来提供一个图像。我还在 IIS 7.5 中使用 URL 重写。

所以图片有这样的 URL: http://mydomain/pictures/ajfhajkfhal/44/thumb.jpg 要么 http://mydomain/pictures/ajfhajkfhal/44.jpg

这被重写为: http://mydomain/Picture.aspx?group=ajfhajkfhal&id=44&thumb=thumb.jpg 要么 http://mydomain/Picture.aspx?group=ajfhajkfhal&id=44

我在 IIS 中添加了缓存规则,以便在请求 JPG 图像时对其进行缓存。这适用于我的图像,这些图像是磁盘上的真实图像。当通过脚本提供图像时,它们总是通过脚本请求,而不被缓存。

图像不会经常更改,因此如果缓存至少保留 30 分钟(或直到文件更改),那将是最好的。

我正在为我的网站使用 .NET/C# 4.0。我尝试在 C# 中设置几个缓存选项,但我似乎无法找到如何缓存这些图像(客户端),而我的静态图像被正确缓存。

编辑我使用以下选项在客户端缓存图像,其中“fileName”是图像的物理文件名(在磁盘上)。

context.Response.AddFileDependency(fileName);
context.Response.Cache.SetETagFromFileDependencies();
context.Response.Cache.SetLastModifiedFromFileDependencies();
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetExpires(DateTime.Now.AddTicks(600));
context.Response.Cache.SetMaxAge(new TimeSpan(0, 5, 0));
context.Response.Cache.SetSlidingExpiration(true);
context.Response.Cache.SetValidUntilExpires(true);
context.Response.ContentType = "image/jpg";

编辑 2 感谢您指出这一点,这确实是一个非常愚蠢的错误;)。我把它改成了从现在开始的 30 分钟(DateTime.Now.AddMinutes(30))。

但这并不能解决问题。我真的认为问题出在Firefox上。我使用 Firebug 来跟踪每个请求,不知何故,我认为我在做一些根本错误的事情。普通图像(缓存和静态)返回响应代码“304(未修改)”,而我的页面总是返回“200(OK)”。

alt text http://images.depl0y.com/capture.jpg

【问题讨论】:

    标签: c# .net asp.net iis-7 caching


    【解决方案1】:

    如果您所说的“脚本”是指 Picture.aspx 中的代码,我应该指出 C# 不是脚本语言,因此从技术上讲它不是脚本。

    您可以使用 ASP.NET 提供的缓存 API。
    我假设您已经有一个包含类似内容的方法。以下是使用缓存 API 的方法:

    string fileName = ... // The name of your file
    byte[] bytes = null;
    
    if (HttpContext.Current.Cache[fileName] != null)
    {
        bytes = (byte[])HttpContext.Current.Cache[fileName];
    }
    else
    {
        bytes = ... // Retrieve your image's bytes
        HttpContext.Current.Cache[fileName] = bytes; // Set the cache
    }
    
    // Send it to the client
    Response.BinaryWrite(bytes);
    Response.Flush();
    

    请注意,您在缓存中使用的键对于每个缓存项必须是唯一的,因此仅使用文件名可能还不够。

    编辑:

    如果要在客户端启用缓存内容,请使用以下命令:

    Response.Cache.SetCacheability(HttpCacheability.Public);
    

    您可以尝试不同的HttpCacheability 值。有了这个,您可以指定内容的缓存方式和位置。 (例如在服务器、代理和客户端上)

    这将使 ASP.NET 向客户端发送带有适当 HTTP 标头的缓存规则。
    这并不能保证客户端会真正缓存它(例如,它取决于浏览器设置),但它会告诉浏览器“你应该缓存这个!”

    最佳做法是在客户端和服务器端都使用缓存。

    编辑 2:

    您的代码有问题是SetExpires(DateTime.Now.AddTicks(600))。 600 个滴答声只是一秒的一小部分...(1 秒 = 10000000 个滴答声)
    基本上,内容会被缓存,但在到达浏览器的那一刻就会过期。

    试试这些:

    context.Response.Cache.SetExpires(DateTime.Now.AddMinutes(5));
    context.Response.Cache.SetMaxAge(TimeSpan.FromMinutes(5));
    

    TimeSpan.FromMinutes 也比 new TimeSpan(...) 更具可读性。)

    【讨论】:

    • 嗯,我猜该文件会被缓存在服务器端,但我希望将图像缓存在客户端(如果在浏览器中启用),但现在似乎只缓存静态图像。
    • @Wim - 您可以通过指定一些 http 标头来使用客户端缓存。这可以通过 ASP.NET 轻松完成,我编辑了答案以向您展示如何操作。
    • @Venemo,这就是我尝试过的。但不知何故,当我处于默认缓存设置时,我的 Firefox 不断重新加载所有图像。当我查看 about:cache 并检查我的图像是否被缓存时,它们就在那里。我认为 Firefox 总是以某种方式重新加载这些图像,即使它们被缓存。我编辑了我的问题,以显示我使用哪些选项来缓存客户端。我认为这在某种程度上是浏览器之类的东西。
    • @Wim - 再次编辑了我的答案。我相信问题出在您设置到期日期的代码中。
    • 不知何故不能解决我的问题。我编辑了我的帖子,向您展示我的标题的响应..
    猜你喜欢
    • 1970-01-01
    • 2015-01-19
    • 2014-04-23
    • 2011-02-21
    • 2017-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    相关资源
    最近更新 更多