Is there a way to force browsers to refresh/download images?
Asked Answered
D

14

74

I have a problem where users are reporting that their images aren't being uploaded and the old ones are still there. On closer inspection the new images are there, they just have the same name as the old one. What I do on the upload is that I rename the images for SEO purposes. When they delete an image the old index becomes available and is reused. Therefore it has the same image name.

Is there a way to (i thought maybe there might be a meta tag for this) to tell the browser to not use its cahce?

The better answer is to rename the image to something totally new. I will get working on that but in the mean time is the quick solution while I work on the bigger problem.

Dorman answered 16/9, 2009 at 7:34 Comment(1)
incase you want to update in cache instead of changing the URL: https://mcmap.net/q/47915/-how-to-force-a-web-browser-not-to-cache-imagesNanananak
R
168

Append a query string with an arbitrary unique number (or time, or version number, etc.):

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

This will result in a new request, because of the different URL.

Rollet answered 16/9, 2009 at 7:36 Comment(8)
+1, but strictly speaking it's not different filename ;-) The filename component is the same, but the URL is certainly different.Chockfull
Gubmo, unique is a bit too much, the best in this case would be to add file's mtime — this way it will only be reloaded when needed.Chockfull
The best way will be to use a version number of the release.Schweiker
@hacker: Randomness doesn’t guarantee that two generated values may not be identical. But uniqueness does guarantee that two generated values are not identical. And isn’t the modification date of that file a unique datum to that file?Lightship
Gumbo, you can, of course, use hash over file contents, but basically, you want the file to be reloaded whenever it is modified and this is when the time stamp is updated in case of normal workflow. You don't want the file to be unconditionally reloaded on each request. Besides, you don't want it to be unique to file — the uniqueness is provided by the uniqueness of filename+query string combination.Chockfull
but if you add ?123 for example once and don't touch it, it will still cache that image right. I'm assuming it will only "recache" if you change it to something different than ?123Octavie
@RobertSinclair yes exactly. Each URL will be cached independently. That's why you could for example append the file modification time, a version number, or a file hash to force a "browser refresh" if the underlying file changes.Rollet
Use ?YYMMDD-HHMMSS of the time the user updated his/her image. This way the image will be reloaded only if it's changed. Not on each browser reload.Grebe
D
25

It's tough. You really want images to be cached, but then you don't want to cache them once a new ones available:

  • Using expires header with a date in the past prevents any caching. Bad
  • Adding a "cache busting" parameter ?342038402 can fix the problem, but can also prevent the image ever from being cached, which is not what you want. Bad.
  • Using expires header with a short (lets say 1 hr) expires is better... after an hour the user will see the image, but your web server won't have to serve it every time. Compromise, but what time works? Not really feasible.

The solution? I can think of two good options:

  • Look into eTags, and your ability to use them. These are designed for this situation. The browser will explicitly ask your server whether the file is up-to-date or not. You can just turn this on in apache if you don't have it aleady.
  • Create a new URL for each new image (and use a far-future expires header). This is what you are working on.
Deafanddumb answered 16/9, 2009 at 9:52 Comment(4)
<quote>"Adding a "cache busting"... Bad." </quote> This is not true, it will force the browser to cache this specific verions for the image, so image.png?342038402 will be cached as that version. If you have the same image with different query string that is bad.Saddlecloth
michaelmol, but then you'll have to manually create a new random number each time the image is changed? I get you don't want it to never cache. using this technique I don't see a way to just upload the image to it's location with the same name and have something programmaticly update the path with a new random numberBlackcock
@ChadMizner If using PHP, you could use PHP's filemtime(string $filename) function in combination with the "cache busting" parameter. That way, the URL for that file will change everytime, the requested file was changed. (Credits to Michael Krelin - hacker).Selfsuggestion
Doesn't matter that you change the value attached to the image url or not. Once there is SOMETHING at the end, your browser will get a fresh copy from the server (Even if that value didn't change). That's why it is BAD!Quitclaim
F
13

My favourite PHP solution:

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

every change of file "create" a new version of the file

Flack answered 30/7, 2019 at 9:46 Comment(1)
I think there is something imbalanced with your quote marks. Looks like the same/similar answer was posted by you below with correct quotes? Maybe edit this to match...Armentrout
A
5

Append the current datetime to the image src:

<img src="yourImage.png?v=<?php echo Date("Y.m.d.G.i.s")?>" />
Arizona answered 5/12, 2012 at 23:2 Comment(1)
You could as well turn off caching, because your example will force the browsers to download the files each time (because the timestamp will change each second). I would suggest removing the i and s at the end, so the timestamp changes every hour. This way the browsers will download the images only once per hour. "Y.m.d.G"Clad
T
4

You can put http-equiv in <meta> tag which will tell browser not to use cache (or even better -- use it in some defined way), but it is better to configure server to send proper http cache headers. Check out article on caching.

Still, some browsers might not support all of http standard, but I believe it's the way to go.

Thapsus answered 16/9, 2009 at 7:41 Comment(1)
On the contrary, using workarounds supports browsers' bad support for these ideas ;) I see your point, and I know further discussion usually leads nowhere - something is "better" but does not work as intended, something is "worse" but do work. It is all up to webdev, what will he/she choose.Thapsus
A
4

Go Random. Just use some random number and append it with image filename.

<img src="image.jpg?<?=rand(1,1000000)?>">
Anglin answered 12/2, 2018 at 18:26 Comment(1)
try to use last-modification-date of file, instead. so you can download the new file only if it was changedFlack
F
4

Another powerfull solution:

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

This print the "last-modification-timestamp" on the path.

New version --> Download new image

Same version --> Take cache's one

Flack answered 12/6, 2020 at 9:18 Comment(0)
P
2

you can control the cache behaviour by playing with the HTTP headers.

setting the expires header in past would force browser to not use cached version.

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

You can consult the RFC to have more details.

Photovoltaic answered 16/9, 2009 at 7:39 Comment(5)
RageZ the problem here is that you will also have to get certain browser's developers consult the RFC.Chockfull
yes ... but at least that the relevant document. after implementation glitch is kind of ...Photovoltaic
I'm all for proper implementation, but we have to deal with reality.Chockfull
Most of browsers implement that correctly, back to the IE6 days that was ugly but now should be fine.Photovoltaic
The browser won't (shouldn't) use the cached version if it requests the image from its HTTP cache. However, if the browser has an in-memory copy of the image, it will sometimes just use that without ever querying its cache. Add a unique fragment identifier to the image URL to ensure it doesn't use an in-memory copy of the image.Dungaree
N
2

If you look at the data that is exchanged between your browser and the server, you'll see that the browser will send a HTTP HEAD request for the images. The result will contain the modification time (but not the actual image data). Make sure that this time changes if the image changes on the server and the browser should download the image again.

Northing answered 16/9, 2009 at 8:12 Comment(1)
Depends on the browser - a lower-latency technique is to use If-Modified-Since header in a GET request. The consequence is still the same - make sure that you correctly report the file's modification time, so that cache invalidation works correctly.Mozambique
F
2

in PHP you can use this trick

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

The time() function show the current timestamp. Every page load is different. So this code deceive the browser: it read another path and it "think" that the image is changed since the user has visited the site the last time. And it has to re-download it, instead of use the cache one.

Flack answered 27/10, 2017 at 8:12 Comment(0)
I
2

It sounds like the concern is more about the primary user seeing their new image than cache being disabled entirely? If that's the case, you can do the following:

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)

If you do this after a new image is uploaded, the browser should see those headers and make a call to the backend, skipping the cache. The new image is now in cache under that URL. The primary user will see the new image, but you still retain all the benefits of caching. Anyone else viewing this image will see updates in a day or so once their cache invalidates.

If the concern was more about making sure all users see the most up to date version, you would want to use one of the other solutions.

Indicative answered 4/12, 2019 at 0:25 Comment(0)
W
1

In PHP you can send a random number or the current timestamp:

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

or

<img src="image.jpg?<?=rand(1,32000)?>">
Wilonah answered 14/1, 2014 at 16:5 Comment(0)
I
1

that was not ok result, I think this is the way to program it correct.

 <td><?php echo "<img heigth=90 width=260 border=1 vspace=2 hspace=2 src=".$row['address']."?=".rand(1,999)."/>" ?></td>
Introspect answered 1/5, 2015 at 7:46 Comment(0)
P
1

I had come up with this issue some times ago. And I was getting data through JSON in AJAX. So what I did is, I just added a Math.random() Javascript function and It worked like a charm. The backend I used was a flask.

<img class="card-img-top w-100 d-block" style="padding:30px;height:400px" src="static/img/${data.image}?${Math.random()} ">
Pursuivant answered 21/4, 2020 at 21:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.