简体   繁体   English

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

[英]how to clear or replace a cached image

I know there are many ways to prevent image caching (such as via META tags), as well as a few nice tricks to ensure that the current version of an image is shown with every page load (such as image.jpg?x=timestamp), but is there any way to actually clear or replace an image in the browsers cache so that neither of the methods above are necessary?我知道有很多方法可以防止图像缓存(例如通过 META 标记),还有一些不错的技巧可以确保每次页面加载时都显示图像的当前版本(例如 image.jpg?x=timestamp ),但是有没有办法真正清除或替换浏览器缓存中的图像,以便上述方法都不是必需的?

As an example, lets say there are 100 images on a page and that these images are named "01.jpg", "02.jpg", "03.jpg", etc. If image "42.jpg" is replaced, is there any way to replace it in the cache so that "42.jpg" will automatically display the new image on successive page loads?举个例子,假设一个页面上有 100 张图像,这些图像被命名为“01.jpg”、“02.jpg”、“03.jpg”等。如果图像“42.jpg”被替换,是有什么方法可以在缓存中替换它,以便“42.jpg”在连续页面加载时自动显示新图像? I can't use the META tag method, because I need everuthing that ISN"T replaced to remain cached, and I can't use the timestamp method, because I don't want ALL of the images to be reloaded every time the page loads.我不能使用 META 标记方法,因为我需要替换 ISN"T 的所有内容以保持缓存,而且我不能使用时间戳方法,因为我不希望每次页面都重新加载所有图像负载。

I've racked my brain and scoured the Internet for a way to do this (preferrably via javascript), but no luck.我绞尽脑汁在互联网上搜索了一种方法来做到这一点(最好通过javascript),但没有运气。 Any suggestions?有什么建议?

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

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

<meta> is absolutely irrelevant. <meta>完全无关紧要。 In fact, you shouldn't try use it for controlling cache at all (by the time anything reads content of the document, it's already cached).事实上,您根本不应该尝试使用它来控制缓存(当任何内容读取文档内容时,它已经被缓存了)。

In HTTP each URL is independent.在 HTTP 中,每个 URL 都是独立的。 Whatever you do to the HTML document, it won't apply to images.无论您对 HTML 文档做什么,它都不适用于图像。

To control caching you could change URLs each time their content changes.要控制缓存,您可以在每次 URL 内容更改时更改 URL。 If you update images from time to time, allow them to be cached forever and use a new filename (with a version, hash or a date) for the new image — it's the best solution for long-lived files.如果您不时更新图像,请允许它们永久缓存并为新图像使用新的文件名(带有版本、哈希或日期)——这是长期文件的最佳解决方案。

If your image changes very often (every few minutes, or even on each request), then send Cache-control: no-cache or Cache-control: max-age= xx where xx is the number of seconds that image is "fresh".如果您的图像经常更改(每隔几分钟,甚至在每次请求时),则发送Cache-control: no-cacheCache-control: max-age= xx其中xx是图像“新鲜”的秒数.

Random URL for short-lived files is bad idea.短期文件的随机 URL 是个坏主意。 It pollutes caches with useless files and forces useful files to be purged sooner.它会用无用的文件污染缓存,并强制更快地清除有用的文件。

If you have Apache and mod_headers or mod_expires then create .htaccess file with appropriate rules.如果您有 Apache 和mod_headersmod_expires则使用适当的规则创建.htaccess文件。

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

Above will make *-nocache.jpg files non-cacheable.以上将使*-nocache.jpg文件不可缓存。

You could also serve images via PHP script (they have awful cachability by default ;)您还可以通过 PHP 脚本提供图像(默认情况下它们具有糟糕的可缓存性;)

Contrary to what some of the other answers have said, there IS a way for client-side javascript to replace a cached image.相反的是一些其他的答案说,有一个客户端JavaScript的方式来替换缓存图像。 The trick is to create a hidden <iframe> , set its src attribute to the image URL, wait for it to load, then forcibly reload it by calling location.reload(true) .诀窍是创建一个隐藏的<iframe> ,将其src属性设置为图像 URL,等待它加载,然后通过调用location.reload(true)强制重新加载它。 That will update the cached copy of the image.这将更新图像的缓存副本。 You may then replace the <img> elements on your page (or reload your page) to see the updated version of the image.然后,您可以替换页面上的<img>元素(或重新加载页面)以查看图像的更新版本。

(Small caveat: if updating individual <img> elements, and if there are more than one having the image that was updated, you've got to clear or remove them ALL, and then replace or reset them. If you do it one-by-one, some browsers will copy the in-memory version of the image from other tags, and the result is you might not see your updated image, despite its being in the cache). (小警告:如果更新单个<img>元素,并且如果有多个更新的图像,则必须将它们全部清除或删除,然后替换或重置它们。如果您这样做-一方面,一些浏览器会从其他标签复制图像的内存版本,结果是您可能看不到更新的图像,尽管它在缓存中)。

I posted some code to do this kind of update here .我在这里发布了一些代码来进行这种更新。

像这样更改图像 url,在查询字符串中添加一个随机字符串。

"image1.jpg?" + DateTime.Now.ToString("ddMMyyyyhhmmsstt");

I'm sure most browsers respect theLast-Modified HTTP header.我确信大多数浏览器都尊重Last-Modified HTTP 标头。 Send those out and request a new image.将它们发送出去并请求新图像。 It will be cached by the browser if the Last-Modified line doesn't change.如果 Last-Modified 行没有改变,它将被浏览器缓存。

You can append a random number to the image which is like giving it a new version.您可以在图像上附加一个随机数,就像给它一个新版本一样。 I have implemented the similar logic and it's working perfectly.我已经实现了类似的逻辑,并且运行良好。

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

The reason the ?x=timestamp trick is used is because that's the only way to do it on a per image basis.使用 ?x=timestamp 技巧的原因是因为这是针对每个图像执行此操作的唯一方法。 That or dynamically generate image names and point to an application that outputs the image.那个或动态生成图像名称并指向输出图像的应用程序。

I suggest you figure out, server side, if the image has been changed/updated, and if so then output your tag with the ?x=timestamp trick to force the new image.我建议您弄清楚,服务器端,图像是否已更改/更新,如果是,则使用 ?x=timestamp 技巧输出您的标签以强制新图像。

No, there is no way to force a file in a browser cache to be deleted, either by the web server or by anything that you can put into the files it sends.不,没有办法强制删除浏览器缓存中的文件,无论是通过 Web 服务器还是通过您可以放入它发送的文件中的任何内容。 The browser cache is owned by the browser, and controlled by the user.浏览器缓存归浏览器所有,由用户控制。

Hence, you should treat each file and each URL as a precious resource that should be managed carefully.因此,您应该将每个文件和每个 URL 视为应谨慎管理的宝贵资源。

Therefore, porneL's suggestion of versioning the image files seems to be the best long-term answer.因此,poroneL 对图像文件进行版本控制的建议似乎是最好的长期答案。 The ETAG is used under normal circumstances, but maybe your efforts have nullified it? ETAG 是在正常情况下使用的,但也许您的努力使其无效? Try changing the ETAG, as suggested.按照建议尝试更改 ETAG。

更改图像的 ETAG。

It sounds like the base of your question is how to get the old version of the image out of the cache.听起来您的问题的基础是如何从缓存中获取旧版本的图像。 I've had success just making a new call and specifying in the header not to pull from cache.我只是成功地进行了一次新调用并在标头中指定不要从缓存中提取。 You're just throwing this away once you fetch it, but the browser's cache should have the updated image at that point.一旦你获取它,你只是把它扔掉,但浏览器的缓存此时应该有更新的图像。

    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)

However, it's important to recognize that this only affects the browser this is called from.但是,重要的是要认识到这只会影响调用它的浏览器。 If you want a new version of the file for any browser once the image is replaced, that will need to be accomplished via server configuration.如果您希望在替换图像后为任何浏览器提供新版本的文件,则需要通过服务器配置来完成。

Here is a solution using the PHP function filemtime():这是使用 PHP 函数 filemtime() 的解决方案:

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

Use the file modified time as a parameter will cause it to read from a cached version until the file has changed.使用文件修改时间作为参数将导致它从缓存版本中读取,直到文件发生更改。 This approach is better than using eg a random number as caching will still work if the file has not changed.这种方法比使用随机数要好,因为如果文件没有改变,缓存仍然可以工作。

I found this article on how to cache bust any file我找到了这篇关于如何缓存任何文件的文章

There are many ways to force a cache bust in this article but this is the way I did it for my image:在本文中有很多方法可以强制清除缓存,但这是我为我的图像所做的方法:

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

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

Notice that you can provide a unique username:password@ combo as a prefix to the domain portion of the uri.请注意,您可以提供唯一的 username:password@ 组合作为 uri 域部分的前缀。 In my experimentation, I've found that inclusion of this with a fake ID (or password I assume) results in the treatment of the resource as unique - thus breaking the caching as you desire.在我的实验中,我发现将其与假 ID(或我假设的密码)包含在一起会导致将资源视为唯一的 - 从而根据需要破坏缓存。

Simply use a timestamp as the username and as far as I can tell the server ignores this portion of the uri as long as authentication is not turned on.只需使用时间戳作为用户名,据我所知,只要未打开身份验证,服务器就会忽略 uri 的这一部分。

Btw - I also couldn't use the tricks above with a google map marker icon caching problem I was having where the ?param=timestamp trick worked, but caused issues with disappearing overlays.顺便说一句 - 我也无法将上面的技巧与谷歌地图标记图标缓存问题一起使用,我在 ?param=timestamp 技巧起作用的地方遇到了问题,但导致了覆盖消失的问题。 Never could figure out why this was happening, but so far so good using this method.永远无法弄清楚为什么会发生这种情况,但到目前为止使用这种方法效果很好。 What I'm unsure of, is if passing fake credentials will have any adverse server performance affects.我不确定的是,传递虚假凭据是否会对服务器性能产生任何不利影响。 If anyone knows I'd be interested to know as I'm not yet in high volume production.如果有人知道我很想知道,因为我还没有进行大批量生产。

Please report back your results.请报告您的结果。

To replace cache for pictore you can store on server-side some version value and when you load picture just send this value instead timestamp.要替换图片的缓存,您可以在服务器端存储一些版本值,当您加载图片时,只需发送此值而不是时间戳。 When your image will be changed change it`s version.当您的图像更改时,请更改其版本。

When changing the image filename is not an option then use a server side session variable and a javascript window.location.reload() function.当不能更改图像文件名时,请使用服务器端会话变量和 javascript window.location.reload()函数。 As follows:如下:

After Upload Complete:上传完成后:

Session("reload") = "yes"

On page_load:在 page_load 上:

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

This allows the client browser to refresh only once because the session variable is reset after one occurance.这允许客户端浏览器仅刷新一次,因为会话变量在一次发生后被重置。

Hope this helps.希望这可以帮助。

In the event that an image is re-uploaded, is there a way to CLEAR or REPLACE the previously cached image client-side?如果图像被重新上传,有没有办法清除或替换以前缓存的图像客户端? In my example above, the goal is to make the browser forget what "42.jpg" is在我上面的例子中,目标是让浏览器忘记“42.jpg”是什么

You're running firefox right?你在运行 Firefox 对吗?

  • Find the Tools Menu找到Tools菜单
  • Select Clear Private Data选择Clear Private Data
  • Untick all the checkboxes except make sure Cache is Checked取消选中所有复选框,但确保选中Cache
  • Press OK按确定

:-) :-)

In all seriousness, I've never heard of such a thing existing, and I doubt there is an API for it.严肃地说,我从来没有听说过这样的东西存在,我怀疑是否有一个 API。 I can't imagine it'd be a good idea on part of browser developers to let you go poking around in their cache, and there's no motivation that I can see for them to ever implement such a feature.我无法想象让浏览器开发人员在他们的缓存中四处闲逛会是一个好主意,而且我看不出他们有任何动机来实现这样的功能。

I CANNOT use the META tag method OR the timestamp method, because I want all of the images cached under normal circumstances.我不能使用 META 标记方法或时间戳方法,因为我希望在正常情况下缓存所有图像。

Why can't you use a timestamp (or etag, which amounts to the same thing)?为什么你不能使用时间戳(或 etag,这相当于同一件事)? Remember you should be using the timestamp of the image file itself , not just Time.Now .请记住,您应该使用图像文件本身的时间戳,而不仅仅是Time.Now
I hate to be the bearer of bad news, but you don't have any other options.我讨厌成为坏消息的承载者,但你别无选择。

If the images don't change, neither will the timestamp, so everything will be cached "under normal circumstances".如果图像没有改变,时间戳也不会改变,所以一切都将“在正常情况下”缓存。 If the images do change, they'll get a new timestamp (which they'll need to for caching reasons), but then that timestamp will remain valid forever until someone replaces the image again.如果图像确实发生了变化,他们将获得一个新的时间戳(出于缓存原因,他们需要这样做),但是该时间戳将永远有效,直到有人再次替换该图像。

Since most, if not all, answers and comments here are copies of parts the question, or close enough, I shall throw my 2 cents in.由于这里的大多数(如果不是全部)答案和评论都是问题部分的副本,或者足够接近,我将投入 2 美分。

I just want to point out that even if there is a way it is going to be difficult to implement.我只想指出,即使有一种方法,也很难实施。 The logic of it traps us.它的逻辑使我们陷入困境。 From a logical stance telling the browser to replace it's cached images for each changed image on a list since a certain date is ideal BUT... When would you take the list down and how would you know if everyone has the latest version who would visit again?从逻辑立场来看,告诉浏览器为自某个日期以来列表中每个更改的图像替换它的缓存图像是理想的但是......你什么时候拿下列表,你怎么知道每个人是否都有最新版本的人会访问再次?

So my 1st "suggestion", as the OP asked for, is this list theory.所以我的第一个“建议”,正如 OP 所要求的,是这个列表理论。

How I see doing this is:我怎么看这样做是:

A.) Have a list that our dynamic and manual changed image urls can be stored. A.) 有一个可以存储我们动态和手动更改的图像 URL 的列表。

B.) Set a dead date where the catch will be reset and the list will be truncated regardless. B.) 设置一个截止日期,在此日期将重置捕获并且无论如何都会截断列表。

C.0) Check list on site entrance vs browser via i frame which could be ran in the background with a shorter cache header set to re-cache them all against the farthest date on the list or something of that nature. C.0) 通过 i 框架检查站点入口与浏览器上的列表,该框架可以在后台运行,并设置较短的缓存标头,以针对列表中的最远日期或类似性质的日期重新缓存它们。

C.1) Using the Iframe or ajax/xhr request I'm thinking you could loop through each image of the list refreshing the page to show a different image and check the cache against it's own modified date. C.1) 使用 Iframe 或 ajax/xhr 请求我认为您可以遍历列表中的每个图像,刷新页面以显示不同的图像,并根据自己的修改日期检查缓存。 So on this image's onload use serverside to decipher if it is not the last image when it is loaded go to the next image.因此,在此图像的 onload 上,使用服务器端来解密它是否在加载时不是最后一个图像,请转到下一个图像。

C.1a) This would mean that our list may need more information per image and I think the obvious one is the possible need of some server side script to adjust the headers as required by each image to minimize the footstep of re-caching changed site images. C.1a) 这意味着我们的列表可能需要每个图像的更多信息,我认为明显的一个是可能需要一些服务器端脚本来调整每个图像所需的标题,以尽量减少重新缓存更改站点的脚步图片。

My 2nd "suggestion" would be to notify the user of changes and direct them to clear their cache.我的第二个“建议”是通知用户更改并指导他们清除缓存。 (Carefully, remove only images and files when possible or warn them of data removal due to the process) (小心,尽可能只删除图像和文件,或警告他们由于该过程而删除数据)

PS This is just an educated ideation. PS 这只是一个受过教育的想法。 A quick theory.一个快速的理论。 If/when I make it I will post the final.如果/当我成功时,我将发布决赛。 Probably not here because it will require server side scripting.可能不在这里,因为它需要服务器端脚本。 This is at least a suggestion not mentioned in the OP's question that he say's he already tried.这至少是 OP 的问题中没有提到的一个建议,他说他已经尝试过了。

After much testing, the solution I have found in the following way.经过多次测试,我通过以下方式找到了解决方案。

1- I create a temporary folder to copy the images with the name adding time () .. (if the folder exists I delete content) 1-我创建一个临时文件夹来复制名称为添加时间 () .. 的图像(如果该文件夹存在,我将删除内容)

2- load the images from that temporary local folder 2- 从该临时本地文件夹加载图像

in this way I always make sure that the browser never caches images and works 100% correctly.通过这种方式,我始终确保浏览器从不缓存图像并且 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.'"/>   ';                  
}

try below solutions,尝试以下解决方案,

myImg.src = " http://localhost/image.jpg ?" myImg.src = " http://localhost/image.jpg ?" + new Date().getTime(); + 新日期().getTime();

Above solutions work for me :)以上解决方案对我有用:)

Try this code snippet:试试这个代码片段:

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

This will make sure that each request is unique, so you will get the latest image always.这将确保每个请求都是唯一的,因此您将始终获得最新的图像。

I usually do the same as @Greg told us, and I have a function for that:我通常和@Greg 告诉我们的一样,我有一个功能:

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

This will work since your server accepts it and you don't use the "magic" parameter any other way.这将起作用,因为您的服务器接受它并且您不会以任何其他方式使用“magic”参数。

I hope it helps.我希望它有帮助。

I have tried something ridiculously simple:我尝试了一些非常简单的事情:

Go to FTP folder of the website and rename the IMG folder to IMG2.转到网站的 FTP 文件夹并将 IMG 文件夹重命名为 IMG2。 Refresh your website and you will see the images will be missing.刷新您的网站,您将看到图像将丢失。 Then rename the folder IMG2 back to IMG and it's done, at least it worked for me in Safari.然后将文件夹 IMG2 重命名回 IMG 就完成了,至少它在 Safari 中对我有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM