如何清除或替换缓存的图像

时间:2008-11-26 19:26:25

标签: javascript image caching replace

我知道有很多方法可以防止图像缓存(例如通过META标签),以及一些很好的技巧来确保每个页面加载时显示当前版本的图像(例如image.jpg? x = timestamp),但有没有办法在浏览器缓存中实际清除或替换图像,以便上述两种方法都不是必需的?

举个例子,假设页面上有100个图像,这些图像被命名为“01.jpg”,“02.jpg”,“03.jpg”等。如果图像“42.jpg”是替换,有没有办法在缓存中替换它,以便“42.jpg”将在连续页面加载时自动显示新图像?我不能使用META标记方法,因为我需要永久性地将ISN“T替换为保持缓存,并且我不能使用timestamp方法,因为我不希望每次页面都重新加载所有图像负荷。

我绞尽脑汁在互联网上寻找一种方法(最好是通过javascript),但没有运气。有什么建议吗?

22 个答案:

答案 0 :(得分:50)

如果您是动态编写页面,可以将最后修改的时间戳添加到URL:

<img src="image.jpg?lastmod=12345678" ...

答案 1 :(得分:11)

<meta>绝对无关紧要。实际上,您根本不应该尝试使用它来控制缓存(当任何内容读取文档的内容时,它已经被缓存)。

在HTTP中,每个URL都是独立的。无论您对HTML文档执行什么操作,它都不适用于图像。

要控制缓存,您可以在每次内容更改时更改网址。如果您不时更新图像,请允许它们永久缓存并为新图像使用新文件名(带有版本,哈希或日期) - 这是长期文件的最佳解决方案。

如果您的图片经常更改(每隔几分钟,甚至每次请求),请发送Cache-control: no-cacheCache-control: max-age= xx ,其中 xx 是图像“新鲜”的秒数。

短期文件的随机URL是个坏主意。它会使用无用的文件污染缓存,并强制更快地清除有用的文件。

如果你有Apache和mod_headersmod_expires,那么请使用适当的规则创建.htaccess文件。

<Files ~ "-nocache\.jpg">
   Header set Cache-control "no-cache"
</Files>

以上将使*-nocache.jpg个文件不可缓存。

您还可以通过PHP脚本提供图像(默认情况下它们具有可靠的可配置性;)

答案 2 :(得分:11)

像这样添加图片网址

<强> “image1.jpg?” + DateTime.Now.ToString(“ddMMyyyyhhmmsstt”);

只需在查询字符串中添加随机字符串

即可

谢谢

Raju Jetla

答案 3 :(得分:8)

与其他一些答案所说的相反, IS 是客户端javascript替换缓存图像的一种方式。诀窍是创建一个隐藏的<iframe>,将其src属性设置为图像URL,等待它加载,然后通过调用location.reload(true)强行重新加载它。这将更新图像的缓存副本。然后,您可以替换页面上的<img>元素(或重新加载页面)以查看图像的更新版本。

(小警告:如果更新单个<img>元素,并且如果有多个图像已更新,则必须清除或删除它们,然后替换或重置它们。你一个接一个地做,一些浏览器会从其他标签复制图像的内存版本,结果是你可能看不到更新的图像,尽管它在缓存中。)

我发布了一些代码来执行此类更新here

答案 4 :(得分:5)

我确信大多数浏览器都尊重Last-Modified HTTP标头。发送出去并请求新图片。如果Last-Modified行没有改变,它将被浏览器缓存。

答案 5 :(得分:4)

您可以在图像上附加一个随机数,就像给它一个新版本一样。我已经实现了类似的逻辑,并且它工作得很好。

<script>
var num = Math.random();
var imgSrc= "image.png?v="+num;
$(function() {
$('#imgID').attr("src", imgSrc);
})
</script>

答案 6 :(得分:1)

这是使用PHP函数filemtime()的解决方案:

<?php 
     $addthis = filemtime('myimf.jpg');
?> 
<img src="myimg.jpg?"<?= $addthis;?> >

使用文件修改时间作为参数,将导致文件从缓存版本中读取,直到文件已更改。这种方法比使用例如随机数,因为如果文件没有更改,缓存仍然可以使用。

答案 7 :(得分:1)

请参阅http://en.wikipedia.org/wiki/URI_scheme

请注意,您可以提供唯一的用户名:password @ combo作为uri域部分的前缀。在我的实验中,我发现将伪造的ID(或我假设的密码)包含在内会导致资源的处理变得独一无二 - 从而打破了你想要的缓存。

只需使用时间戳作为用户名,只要我没有打开身份验证,服务器就会忽略uri的这一部分。

顺便说一句 - 我也无法使用谷歌地图标记图标缓存问题上面的技巧我在哪里?param = timestamp技巧工作,但导致问题与消失的叠加。从来没有弄清楚为什么会这样,但到目前为止使用这种方法是如此的好。我不确定的是,如果传递假凭证会对服务器性能产生任何不利影响。如果有人知道我有兴趣知道,因为我还没有大批量生产。

请报告您的结果。

答案 8 :(得分:1)

听起来您的问题的基础是如何从缓存中获取旧版本的图像。我已经成功完成了一个新的调用,并在标头中指定了不要从缓存中提取。一旦获取它,您就将其丢弃,但是浏览器的缓存此时应具有更新的图像。

    var headers = new Headers()
    headers.append('pragma', 'no-cache')
    headers.append('cache-control', 'no-cache')

    var init = {
      method: 'GET',
      headers: headers,
      mode: 'no-cors',
      cache: 'no-cache',
    }

    fetch(new Request('path/to.file'), init)

但是,重要的是要认识到这只会影响从其调用的浏览器。如果您希望在替换图像后为任何浏览器提供文件的新版本,则需要通过服务器配置来实现。

答案 9 :(得分:1)

使用?x = timestamp技巧的原因是因为这是基于每个图像执行此操作的唯一方法。那或动态生成图像名称并指向输出图像的应用程序。

我建议你弄清楚服务器端,如果图像已被更改/更新,如果是,那么输出你的标签,用?x =时间戳技巧来强制新图像。

答案 10 :(得分:0)

我发现了 this article 一个如何缓存任何文件的方法

在本文中有很多方法可以强制清除缓存,但这是我为我的图像所做的方法:

fetch('/thing/stuck/in/cache', {method:'POST', credentials:'include'});

答案 11 :(得分:0)

经过多次测试,我找到的解决方法如下。

1- 我创建一个临时文件夹来复制名称为添加时间 () .. 的图像(如果文件夹存在我删除内容)

2- 从该临时本地文件夹加载图像

通过这种方式,我始终确保浏览器永远不会缓存图像并且 100% 正确工作。

if (!is_dir(getcwd(). 'articulostemp')){
    $oldmask = umask(0);mkdir(getcwd(). 'articulostemp', 0775);umask($oldmask);
}else{
    rrmfiles(getcwd(). 'articulostemp');
}   
foreach ($images as $image) { 
    $tmpname = time().'-'.$image;
    $srcimage = getcwd().'articulos/'.$image;
    $tmpimage = getcwd().'articulostemp/'.$tmpname;
    copy($srcimage,$tmpimage);
    $urlimage='articulostemp/'.$tmpname;
    echo '  <img loading="lazy" src="'.$urlimage.'"/>   ';                  
}

答案 12 :(得分:0)

由于这里的大多数(如果不是全部)答案和评论都是问题的一部分或足够接近,我将投入2美分。

我只想指出,即使有一种方法也很难实现。它的逻辑困住了我们。从逻辑上讲告诉浏览器,因为某个日期是理想的,所以用列表中的每个更改的图像替换它的缓存图像,但是理想的情况是...什么时候删除列表以及如何知道每个人是否都有最新版本的用户可以访问再来一次?

因此,正如OP所要求的,我的第一个“建议”就是这种列表理论。

我对此的看法是:

A。)有一个列表,可以存储我们的动态和手动更改的图像URL。

B。)设置一个死日期,在该日期之前,无论如何都将重置渔获物,并且列表将被截断。

C.0)通过i框架检查网站入口与浏览器的列表,该列表可以在后台运行,并设置一个较短的缓存头,以针对列表中最远的日期或类似性质的内容重新缓存它们。 / p>

C.1)使用Iframe或ajax / xhr请求,我想您可以遍历列表的每个图像,刷新页面以显示不同的图像,并对照其自己的修改日期检查缓存。因此,在此图像的onload上,请使用服务器端解密,如果它不是最后一张图像,则转到下一张图像。

C.1a),这意味着我们的列表可能需要每张图像更多的信息,我认为显而易见的是,可能需要一些服务器端脚本来根据每张图像的要求调整标头,以最大程度地减少重新打印的脚步。缓存更改的站点图像。

我的第二个“建议”是通知用户更改,并指示他们清除其缓存。 (请注意,请尽可能仅删除图像和文件,或警告该过程可能会导致数据删除)

P.S。这只是一个有教养的想法。快速理论。如果/当我做到这一点时,我将发布决赛。可能不在此处,因为它将需要服务器端脚本。至少在OP的问题中没有提及他说他已经尝试过的建议。

答案 13 :(得分:0)

我通常和@Greg告诉我们一样,我有一个功能:

function addMagicRefresh(url)
{
    var symbol = url.indexOf('?') == -1 ? '?' : '&';
    var magic = Math.random()*999999;
    return url + symbol + 'magic=' + magic;
}

这将有效,因为您的服务器接受它并且您不使用&#34;魔法&#34;参数任何其他方式。

我希望它有所帮助。

答案 14 :(得分:0)

试试这段代码:

var url = imgUrl? + Math.random();

这将确保每个请求都是唯一的,因此您将始终获得最新的图像。

答案 15 :(得分:0)

尝试以下解决方案,

myImg.src =&#34; http://localhost/image.jpg?&#34; + new Date()。getTime();

以上解决方案适合我:)

答案 16 :(得分:0)

要替换图片缓存,您可以在服务器端存储某个版本值,当您加载图片时,只需发送此值而不是时间戳。当您的图像被更改时,请更改它的版本。

答案 17 :(得分:0)

更改图像的ETAG。

答案 18 :(得分:0)

当更改图像文件名不是一个选项时,则使用服务器端会话变量和javascript window.location.reload()函数。如下:

上传完成后:

Session("reload") = "yes"

在page_load上:

If Session("reload") = "yes" Then
    Session("reload") = Nothing
    ClientScript.RegisterStartupScript(Me.GetType), "ReloadImages", "window.location.reload();", True)
End If

这允许客户端浏览器只刷新一次,因为会话变量在一次出现后被重置。

希望这有帮助。

答案 19 :(得分:0)

不,无法通过Web服务器或您可以放入其发送的文件中的任何内容强制删除浏览器缓存中的文件。浏览器缓存由浏览器拥有,并由用户控制。

因此,您应该将每个文件和每个URL视为应该谨慎管理的宝贵资源。

因此,porneL建议对图像文件进行版本控制似乎是最好的长期答案。 ETAG在正常情况下使用,但也许你的努力已经取消了它?尝试按照建议更改ETAG。

答案 20 :(得分:0)

  

如果重新上传图像,有没有办法清除或更换以前缓存的图像客户端?在我上面的例子中,目标是让浏览器忘记“42.jpg”是什么

你正在运行firefox吗?

  • 找到Tools菜单
  • 选择Clear Private Data
  • 取消选中所有复选框,但确保Cache已选中
  • 按OK

: - )

严肃地说,我从来没有听说过存在这样的事情,我怀疑它有一个API。我无法想象,对于部分浏览器开发人员来说,让你在他们的缓存中进行探索是个好主意,并且我没有动力让他们能够实现这样的功能。

  

我不能使用META标记方法或时间戳方法,因为我希望在正常情况下缓存所有图像。

为什么你不能使用时间戳(或etag,它相同的东西)?请记住,您应该使用图像文件本身的时间戳 ,而不仅仅是Time.Now
我不想成为坏消息的承载者,但你没有其他任何选择。

如果图像没有改变,时间戳也不会改变,所以一切都将在“正常情况下”缓存。如果图像确实发生变化,他们将获得一个新的时间戳(他们需要出于缓存的原因),但随后该时间戳将永久有效,直到有人再次替换图像为止。

答案 21 :(得分:-1)

我尝试过一些非常简单的事情:

转到网站的FTP文件夹,将IMG文件夹重命名为IMG2。刷新您的网站,您将看到图像将丢失。然后将文件夹IMG2重命名为IMG并完成,至少它在Safari中适用于我。