Javascript 使浏览器重新验证(但不一定重新蚀刻)图像

Javascript 使浏览器重新验证(但不一定重新蚀刻)图像,javascript,html,Javascript,Html,在我的web应用程序中,我们为所有图像提供了24小时有效的HTTP缓存头,以及ETag。但有时Javascript客户端应用程序会怀疑图像可能已更新。在这些情况下,我想强制浏览器重新验证图像缓存,而不实际破坏缓存 例如,我得到一个用户记录(JSON格式),上面有最近一次更新的日期。最近更新的日期可能发生变化的原因有几个:用户可能更改了昵称,或者加入了新的董事会,或者更改了他们的图像。所以图像很有可能没有改变,但我们需要检查一下 我知道我可以在URL后面附加一个缓存中断器来重新请求图像。但这将迫使

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

例如,我得到一个用户记录(JSON格式),上面有最近一次更新的日期。最近更新的日期可能发生变化的原因有几个:用户可能更改了昵称,或者加入了新的董事会,或者更改了他们的图像。所以图像很有可能没有改变,但我们需要检查一下

我知道我可以在URL后面附加一个缓存中断器来重新请求图像。但这将迫使图像重新加载,无论它是否已更改,导致浏览器缓存中出现两个条目,并迫使我用新的url更新所有图像。我真正想要的是让浏览器重新请求相同的URL,如果不匹配和/或如果请求中的标题已修改,则发送正确的URL,这样,如果图像未更改,它将获得304


有没有办法用Javascript实现这一点

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


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

这实际上很容易实现。使用
缓存控制
标题设置为
max age=0
,对图像发出AJAX请求

服务器必须使用更新的映像(和一组新的缓存标头)或包含
缓存控件
标头的304响应,如
public,max age=123

带有
缓存控制
标题的304非常重要,因为它指示浏览器更新与资源相关的新鲜度信息

请求完成后,删除旧的

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

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

在Chrome的网络检查器中,您会看到两个请求:AJAX请求,然后通过重新插入
生成的请求没有兄弟节点,也没有属性/类/等等。。。

parent.append('听起来你好像想得太多了。即使图像没有更改,重新获取图像真的会这么糟糕吗?我可能有几十张图像要检查。可能需要下载很多,尤其是在移动设备上。如果我可以在不每次重新加载的情况下重新验证它们,我可以更频繁地检查它们。另外,我还可以我认为这是一个有趣的问题移动设备?你为什么不在你的问题中提到这一点?这似乎很贴切。它不是特定于移动设备的。它只是一个网络应用程序,但你现在不能忽视平板电脑。我认为这是符合规范的行为?我快速整理了一个JSFIDLE,看看如果我删除并重新添加图像会发生什么。它不会刷新在我尝试过的任何现代浏览器中,我都会使用m缓存。不幸的是,在我的环境中,这并不能真正起作用。它是一个单页Javascript应用程序,因此页面很少重新加载。我需要了解页面加载之间发生的变化。即使是js发送的请求,在我看来,仍然是关于服务器端的ETag和响应代码。缓存是b在处理图像时,朋友和敌人是不同的。这在firefox或IE中不起作用-只在Chrome中起作用
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);
        }
    });
}