【问题标题】:Is there a way to force browsers to refresh/download images?有没有办法强制浏览器刷新/下载图像?
【发布时间】:2010-11-28 17:25:19
【问题描述】:

我遇到了一个问题,用户报告他们的图片没有上传,而旧的图片仍然存在。仔细检查后,新图像就在那里,它们只是与旧图像具有相同的名称。我在上传时所做的是重命名图像以用于 SEO 目的。当他们删除图像时,旧索引变得可用并被重复使用。因此,它具有相同的图像名称。

有没有办法(我想可能有一个元标记)告诉浏览器不要使用它的cahce?

更好的答案是将图像重命名为全新的名称。我会着手解决这个问题,但与此同时,在我解决更大的问题时,这是一个快速的解决方案。

【问题讨论】:

    标签: html browser browser-cache image-caching


    【解决方案1】:

    附加一个带有任意唯一编号(或时间、或版本号等)的查询字符串:

    <img src="image.png?80172489074" alt="a cool image" />
    

    这将导致新的请求,因为 URL 不同。

    【讨论】:

    • +1,但严格来说不是文件名不同 ;-) 文件名组件是一样的,但是 URL 肯定是不同的。
    • Gubmo,unique 有点太多了,在这种情况下最好是添加文件的 mtime - 这样它只会在需要时重新加载。
    • 最好的方法是使用版本号。
    • @hacker:随机性并不能保证两个生成的值可能不相同。但是唯一性确实保证了两个生成的值不相同。而且该文件的修改日期不是该文件的唯一数据吗?
    • @RobertSinclair 是的。每个 URL 将被独立缓存。这就是为什么您可以附加文件修改时间、版本号或文件哈希以在基础文件更改时强制“浏览器刷新”的原因。
    【解决方案2】:

    这很难。您确实希望图像被缓存,但是一旦有新图像可用,您就不想缓存它们:

    • 使用具有过去日期的 expires 标头可防止任何缓存。不好
    • 添加“缓存破坏”参数 ?342038402 可以解决问题,但也可以防止图像被缓存,这不是您想要的。不好。
    • 使用 expires 标头和较短的(假设为 1 小时) expires 更好...一小时后,用户将看到图像,但您的 Web 服务器不必每次都提供它。妥协,但什么时间有效?不太可行。

    解决方案?我能想到两个不错的选择:

    • 查看电子标签以及您使用它们的能力。这些是针对这种情况设计的。浏览器将明确询问您的服务器文件是否是最新的。如果你没有它,你可以在 apache 中打开它。
    • 为每个新图像创建一个新 URL(并使用一个遥远的未来过期标头)。这就是你正在做的事情。

    【讨论】:

    • “添加一个“缓存破坏”......不好。” 这不是真的,它会强制浏览器为图像缓存这个特定的版本,所以 image.png?342038402 将被缓存为那个版本。如果您有相同的图像和不同的查询字符串,那就不好了。
    • michaelmol,但是每次更改图像时您都必须手动创建一个新的随机数?我知道你不希望它永远缓存。使用这种技术,我看不到一种方法可以将图像上传到具有相同名称的位置,并以编程方式使用新的随机数更新路径
    • @ChadMizner 如果使用 PHP,您可以将 PHP 的 filemtime(string $filename) 函数与“缓存清除”参数结合使用。这样,该文件的 URL 每次都会更改,请求的文件已更改。 (感谢 Michael Krelin - 黑客)。
    • 是否更改附加到图像 url 的值并不重要。一旦最后有一些东西,你的浏览器将从服务器获得一个新的副本(即使那个值没有改变)。这就是为什么它很糟糕!
    【解决方案3】:

    我最喜欢的 PHP 解决方案:

    <img src="<?php echo "image.jpg" . "?v=" . filemtime("image.jpg"); ?>" />
    

    文件的每次更改都会“创建”文件的新版本

    【讨论】:

      【解决方案4】:

      将当前日期时间附加到图像 src:

      <img src="yourImage.png?v=<?php echo Date("Y.m.d.G.i.s")?>" />
      

      【讨论】:

      • 您也可以关闭缓存,因为您的示例将强制浏览器每次下载文件(因为时间戳每秒都会更改)。我建议在最后删除 i 和 s,因此时间戳每小时都会更改。这样,浏览器每小时只会下载一次图像。 “Y.m.d.G”
      【解决方案5】:

      您可以将http-equiv 放在&lt;meta&gt; 标记中,这将告诉浏览器不要使用缓存(甚至更好——以某种定义的方式使用它),但最好配置服务器以发送正确的http cache标题。查看article on caching

      不过,有些浏览器可能不支持所有 http 标准,但我相信这是要走的路。

      【讨论】:

      • 相反,使用变通办法支持浏览器对这些想法的不良支持;)我明白你的意思,而且我知道进一步的讨论通常无济于事 - 有些东西“更好”但不能按预期工作,有些事情“更糟”但确实有效。这完全取决于 webdev,他/她会选择什么。
      【解决方案6】:

      随机。只需使用一些随机数并将其附加图像文件名即可。

      <img src="image.jpg?<?=rand(1,1000000)?>">
      

      【讨论】:

      • 尝试使用文件的最后修改日期。因此只有在新文件发生更改时才能下载新文件
      【解决方案7】:

      另一个强大的解决方案:

      <img src="image.png?v=<?php echo filemtime("image.png"); ?>" />
      

      这会在路径上打印“last-modification-timestamp”

      新版本 --> 下载新图片

      相同的版本 --> 取缓存的一个

      【讨论】:

        【解决方案8】:

        您可以通过使用 HTTP 标头来控制缓存行为。

        在过去设置 expires 标头会强制浏览器不使用缓存版本。

        Expires: Sat, 26 Jul 1997 05:00:00 GMT
        

        您可以咨询RFC了解更多详情。

        【讨论】:

        • RageZ 这里的问题是您还必须让某些浏览器的开发人员查阅 RFC。
        • 是的......但至少是相关文件。实施后故障有点......
        • 我完全赞成正确实施,但我们必须面对现实。
        • 大多数浏览器都正确实现了这一点,回到 IE6 时代,那是丑陋的,但现在应该没问题。
        • 浏览器不会(不应该)使用缓存版本如果它从其 HTTP 缓存请求图像。但是,如果浏览器有图像的内存副本,它有时会直接使用它而不查询其缓存。向图像 URL 添加唯一的片段标识符,以确保它不使用图像的内存副本。
        【解决方案9】:

        如果您查看浏览器和服务器之间交换的数据,您会看到浏览器将发送一个 HTTP HEAD 请求以获取图像。结果将包含修改时间(但不包含实际图像数据)。如果服务器上的图像发生更改,请确保此时间发生更改,并且浏览器应再次下载图像。

        【讨论】:

        • 取决于浏览器 - 一种较低延迟的技术是在 GET 请求中使用 If-Modified-Since 标头。结果还是一样——确保你正确报告了文件的修改时间,这样缓存失效才能正常工作。
        【解决方案10】:

        在 PHP 中你可以使用这个技巧

        <img src="image.png?<?php echo time(); ?>" />
        

        time() 函数显示当前时间戳。每个页面加载都是不同的。所以这段代码欺骗了浏览器:它读取了另一个路径,并“认为”自从用户上次访问该站点以来图像已更改。而且它必须重新下载它,而不是使用缓存。

        【讨论】:

          【解决方案11】:

          听起来更关心的是主要用户看到他们的新图像而不是缓存被完全禁用?如果是这种情况,您可以执行以下操作:

          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)
          

          如果您在上传新图片后执行此操作,浏览器应该会看到这些标头并调用后端,跳过缓存。新图像现在在该 URL 下的缓存中。主要用户将看到新图像,但您仍然保留缓存的所有好处。一旦缓存失效,其他任何查看此图像的人都会在一天左右看到更新。

          如果更关心的是确保所有用户都能看到最新版本,您可能希望使用其他解决方案之一。

          【讨论】:

            【解决方案12】:

            在 PHP 中你可以发送一个随机数或当前时间戳:

            <img src="image.jpg?<?=Date('U')?>">
            

            <img src="image.jpg?<?=rand(1,32000)?>">
            

            【讨论】:

              【解决方案13】:

              这不是好的结果,我认为这是正确编程的方法。

               <td><?php echo "<img heigth=90 width=260 border=1 vspace=2 hspace=2 src=".$row['address']."?=".rand(1,999)."/>" ?></td>
              

              【讨论】:

                【解决方案14】:

                我之前就提出过这个问题。我正在通过 AJAX 中的 JSON 获取数据。 所以我所做的是,我只是添加了一个 Math.random() Javascript 函数,它就像一个魅力。 我使用的后端是一个烧瓶。

                &lt;img class="card-img-top w-100 d-block" style="padding:30px;height:400px" src="static/img/${data.image}?${Math.random()} "&gt;

                【讨论】:

                  猜你喜欢
                  • 2014-06-21
                  • 1970-01-01
                  • 2023-04-09
                  • 2016-01-11
                  • 1970-01-01
                  • 2015-12-09
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-09-04
                  相关资源
                  最近更新 更多