我的网站上的用户生成图片是通过给他们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,因为它更适合以后有关压缩的需求等。)
答案 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(确实需要时间戳)。