4

在我的 Web 应用程序中,我们提供所有带有 24 小时有效 HTTP 缓存标头的图像,以及 ETags。但有时 Javascript 客户端应用程序有理由怀疑图像可能已更新。在这些情况下,我想强制浏览器重新验证图像缓存,而不实际破坏缓存。

例如,我得到一个用户记录(JSON 格式),其中包含最近的 LastUpdated 日期。LastUpdated 日期更改的可能原因有多种:用户可能更改了昵称、加入了新版块或更改了图像。所以很有可能图像没有改变,但我们需要检查。

我知道我可以重新请求带有附加到 URL 的缓存中断器的图像。但这将强制图像重新加载,无论它是否已更改,导致浏览器缓存中有两个条目,并迫使我用新的 url 更新我的所有图像。我真正想要的是让浏览器重新请求相同的 URL,并在请求中发送正确的 If-None-Match 和/或 If-Modified-Since 标头,这样如果图像没有更改,它将获得 304 .

有没有办法在 Javascript 中实现这一点?

4

2 回答 2

0

这实际上很容易实现。Cache-Control对标头设置为 的图像发出 AJAX 请求max-age=0

服务器必须使用更新的图像(和一组新的缓存标头)包含Cache-Control类似public, max-age=123.

带有Cache-Control标头的 304 非常重要,因为它指示浏览器更新与资源关联的新鲜度信息。

当请求完成时,<img>从 DOM 中删除旧元素并重新插入一个指向相同的新元素src

这是有效的,因为请求 Cache-Control标头告诉浏览器忽略其缓存并转到网络。当浏览器收到响应时,它会更新它的缓存——即使您实际上并没有对 AJAX 结果做任何事情。

现在,当您删除旧元素并插入新元素时,浏览器会直接从其缓存中获取最近更新的图像。

在 Chrome 的网络检查器中,您会看到两个请求:AJAX 请求,然后是通过重新插入<img>元素生成的请求。但是,如果服务器Cache-Control正确设置了标头,则第二个“请求”将由浏览器的缓存完成,并且实际上不会通过网络发送任何内容。

function updateImage(el) {
    el = $(el);
    var src = el.attr('src');

    $.ajax({
        url: src,
        headers: {
            'Cache-Control': 'max-age=0'
        },
        success: function() {
            var parent = el.parent(); 
            el.remove();
            // this assumes that the <img> has no siblings and no attributes/classes/etc...
            parent.append('<img>').attr('src',src);
        }
    });
}
于 2013-07-14T23:30:51.640 回答
0

由于图像存在于服务器中,在缓存中,服务器是需要进行查询的地方。我会在页面加载之前进行检查,如果需要,强制服务器更新缓存中的特定图像。“HTML”部分应始终假定所有 img-tags 等都是正确的。

更新服务器缓存中单个文件的最佳方法是 IMO 的另一头野兽。

于 2012-04-20T17:51:43.793 回答