强制浏览器刷新缓存的etaged图像

时间:2011-10-27 14:02:14

标签: caching browser http-headers

我的网站上的用户生成图片是通过给他们src这样提供的:

userImage.ashx?id={UserId}&type=avatar

ashx文件的响应中,我设置了etag标头。当用户上传新图像时,etag会更改。

如果浏览器有一个缓存了etag的文件,那么只要需要显示该文件,它就应该向服务器发送一个请求,并将If-None-Match标头设置为该etag。如果缓存的etag与服务器上的当前etag相同,则服务器将以Not Modified - 304响应。如果etag不同,则服务器以OK - 200响应并开始发送新文件。

这是理论上应该如何运作的。但是,我发现对于某些浏览器(firefox和IE,未经测试的其他浏览器),情况并非如此。如果用户导航到具有缓存的etagged图像的新页面,则这些浏览器只是在不提出请求的情况下使用其缓存中的图像。如果用户然后刷新页面,则浏览器发送带有If-None-Match标头集的请求。

所以我的问题是:用户更新其中一个图像,然后导航到显示图像的页面。在用户按下refresh之前,将显示缓存的图像,即使它与新图像具有不同的etag。当用户按下刷新时,浏览器会执行If-None-Match标头设置的请求,这会触发服务器发送新图像。

有可能解决这个问题吗?

示例200响应头:

Status=OK - 200
Date=Thu, 27 Oct 2011 14:37:31 GMT
Server=Microsoft-IIS/6.0
X-Powered-By=ASP.NET
X-AspNet-Version=4.0.30319
Transfer-Encoding=chunked
Cache-Control=public, max-age=86400
Etag="27/10/2011 13:23:30"
Content-Type=image/jpg

示例304标题:

Status=Not Modified - 304
Connection=close
Date=Thu, 27 Oct 2011 14:39:12 GMT
Server=Microsoft-IIS/6.0
X-Powered-By=ASP.NET
X-AspNet-Version=4.0.30319
Cache-Control=public, max-age=86400

(使用上次修改日期作为etag,因为它更适合以后有关压缩的需求等。)

2 个答案:

答案 0 :(得分:2)

IIRC您可以通过“Expires”标题设置文件的有效期。因此,如果您说“此文件在接下来的两天内有效”,则浏览器没有理由联系您的服务器。

你的例子中给出的max-age基本上做了同样的事情。

答案 1 :(得分:0)

我解决了这个问题如下:

让服务器端服务始终重定向(暂时移动302)到您要显示的图像,并在用户端将图像源重置为重定向+'?' +时间戳。

这会强制浏览器再次查询图像,但让缓存工作。

所以,例如您的用户端javascript请求/redirectme/avatar-xxx.jpg?121341并获得302/avatars/avatar-xxx.jpg,然后通过Etag缓存正常请求{{1}}。为了不必每次都发送整个图像,您需要支付两次往返费用。

在Chrome 19中测试(不需要时间戳查询字符串)和Firefox 10(确实需要时间戳)。