270

Is it possible to reload an image with an identical file name from a server using jQuery?

For example, I have an image on a page, however, the physical image can change based on user actions. Note, this does not mean the file name changes, but the actual file itself.

ie:

  • User views image on default page
  • User uploads new image
  • Default image on page does not change(I assume this is due to the file name being identical, the browser uses the cached version)

Regardless of how often the code below is called, the same issue persists.

$("#myimg").attr("src", "/myimg.jpg");

In the jQuery documentation, the "load" function would be perfect if it had a default method of firing the event as opposed to binding a callback function to a successful/complete load of an element.

Any assistance is greatly appreciated.

Alexis Abril
  • 6,389
  • 6
  • 33
  • 53
  • 1
    @Alexis, is your issue that the image is cached in the browser and won't update after it's been changed on the server? – jay Jan 20 '10 at 21:06
  • 1
    @jeerose, I believe this is the issue as the file actually does change(same filename) and is reflected on the page if you do a full page refresh. – Alexis Abril Jan 21 '10 at 16:16

14 Answers14

574

It sounds like it's your browser caching the image (which I now notice you wrote in your question). You can force the browser to reload the image by passing an extra variable like so:

d = new Date();
$("#myimg").attr("src", "/myimg.jpg?"+d.getTime());
jay
  • 10,275
  • 5
  • 34
  • 52
  • 1
    Adding a query string variable completely passed my mind. This solved it and the image now reloads on request. – Alexis Abril Jan 21 '10 at 16:17
  • 4
    It works, and it is a nice workaround, but still a workaround! Is there no different way of fetching the image telling the browser to forget about the cached one? – spuas Jul 03 '13 at 09:16
  • I have a really picky webcam that seems to forbid any requests for static images that contain parameters. Ugh. This is a great solution otherwise. – dangowans Feb 04 '14 at 21:20
  • First Google Result, so.. This is my preferred method as it always works on any browser and server.. But otherwise you can use a htaccess file or serve the image through a client side script. These are a cleaner approach and allow for other features and uses – Angry 84 Jun 19 '14 at 13:16
  • You don't understand how this shizzle helped mah lifez! – Guy Mazuz Apr 20 '15 at 23:37
  • This is great! But why not use Math.random() ? – Tomas Gonzalez Oct 28 '15 at 05:40
  • 3
    @TomasGonzalez B/c there *is* a chance of getting a collision with `random`, and shouldn't ever be with `Date` unless you're *really really* quick. ;^) Getting a date on the client isn't that resource intensive, and you could reuse for as many images as you need to pull at once, so proceed to step 4. Profit. – ruffin Dec 19 '15 at 16:41
  • This solution worked for me for years, but alas, the server I fetch images from now returns a broken link if the file name isn't _exact_. Any other workaround would be much appreciated. – felwithe Dec 13 '16 at 14:35
  • and if the image was already loaded using a parameter? like /image/getimage?id=2 – Daniel Jun 21 '18 at 16:35
  • 1
    I've posted a new method below that I couldn't find on any answer, and it causes the browser to ignore the cache and fetch a new copy using an unmodified URL. This was important for me because the original URL is the only one provided by the web server and this method didn't help beyond the first download. – Pluto Nov 12 '21 at 23:43
  • Check out Pluto's answer if you don't want to have to add a timestamp to every single use of your image across the site. – jerclarke Jun 22 '23 at 22:11
58

It's probably not the best way, but I've solved this problem in the past by simply appending a timestamp to the image URL using JavaScript:

$("#myimg").attr("src", "/myimg.jpg?timestamp=" + new Date().getTime());

Next time it loads, the timestamp is set to the current time and the URL is different, so the browser does a GET for the image instead of using the cached version.

Kaleb Brasee
  • 51,193
  • 8
  • 108
  • 113
  • 2
    This worked for me for years, but today my image server (not controlled by me) started returning a broken link if the file name isn't exact. If anyone has another workaround it would be much appreciated. Unfortunately every answer in this thread is a variation on this one. – felwithe Dec 13 '16 at 14:44
  • @felwithe, may be this server looks only for extension in the end of query? So you can try to test this approach: `imagename.jpg?t=1234567&q=.jpg` or `imagename.jpg#t1234567.jpg` – FlameStorm Mar 16 '17 at 13:20
29

This could be one of the two problems you mention yourself.

  1. The server is caching the image
  2. The jQuery does not fire or at least doesn't update the attribute

To be honest, I think it's number two. Would be a lot easier if we could see some more jQuery. But for a start, try remove the attribute first, and then set it again. Just to see if that helps:

$("#myimg").removeAttr("src").attr("src", "/myimg.jpg");

Even if this works, post some code since this is not optimal, imo :-)

Kordonme
  • 2,314
  • 3
  • 20
  • 32
  • @Kordonme, is this where someone comments about "bad" jQuery? (I'm joking, I'm joking) ;) – jay Jan 21 '10 at 15:06
  • @Kordonme, this is actually held in an event handler and at the moment is the only line of code. I've added an alert just before this line just to verify the event is actually firing. The event fires with no errors. – Alexis Abril Jan 21 '10 at 16:14
  • 3
    I have a really picky webcam that seems to forbid any requests for static images that contain parameters. Ugh. This is a great solution for my unique case. Thanks. – dangowans Feb 04 '14 at 21:22
  • This is the best answer if you don't want/need residual parameters – RafaSashi Jul 19 '17 at 16:06
  • Thanks this helped (it only cached it for me in Chrome) – Daniel Resch Aug 13 '18 at 11:41
14

with one line with no worries about hardcoding the image src into the javascript (thanks to jeerose for the ideas:

$("#myimg").attr("src", $("#myimg").attr("src")+"?timestamp=" + new Date().getTime());
Radu
  • 658
  • 5
  • 13
  • 14
    Just be careful because this will infinitely add more and more characters onto the end of the URL – Alfo Nov 16 '12 at 23:35
9

To bypass caching and avoid adding infinite timestamps to the image url, strip the previous timestamp before adding a new one, this is how I've done it.

//refresh the image every 60seconds
var xyro_refresh_timer = setInterval(xyro_refresh_function, 60000);

function xyro_refresh_function(){
//refreshes an image with a .xyro_refresh class regardless of caching
    //get the src attribute
    source = jQuery(".xyro_refresh").attr("src");
    //remove previously added timestamps
    source = source.split("?", 1);//turns "image.jpg?timestamp=1234" into "image.jpg" avoiding infinitely adding new timestamps
    //prep new src attribute by adding a timestamp
    new_source = source + "?timestamp="  + new Date().getTime();
    //alert(new_source); //you may want to alert that during developement to see if you're getting what you wanted
    //set the new src attribute
    jQuery(".xyro_refresh").attr("src", new_source);
}
sEver
  • 1,948
  • 1
  • 16
  • 10
6

This works great! however if you reload the src multiple times, the timestamp gets concatenated to the url too. I've modified the accepted answer to deal with that.

$('#image_reload_button').on('click', function () {
    var img = $('#your_image_selector');
    var src = img.attr('src');
    var i = src.indexOf('?dummy=');
    src = i != -1 ? src.substring(0, i) : src;

    var d = new Date();
    img.attr('src', src + '?dummy=' + d.getTime());
});
userlond
  • 3,632
  • 2
  • 36
  • 53
kasper Taeymans
  • 6,950
  • 5
  • 32
  • 51
3

Have you tried resetting the image containers html. Of course if it's the browser that is caching then this wouldn't help.

function imageUploadComplete () {
    $("#image_container").html("<img src='" + newImageUrl + "'>");
}
Matti Lyra
  • 12,828
  • 8
  • 49
  • 67
2

Some times actually solution like -

$("#Image").attr("src", $('#srcVal').val()+"&"+Math.floor(Math.random()*1000));

also not refresh src properly, try out this, it worked for me ->

$("#Image").attr("src", "dummy.jpg");
$("#Image").attr("src", $('#srcVal').val()+"&"+Math.floor(Math.random()*1000));
1

Using "#" as a delimiter might be useful

My images are kept in a "hidden" folder above "www" so that only logged users are allowed access to them. For this reason I cannot use the ordinary <img src=/somefolder/1023.jpg> but I send requests to the server like <img src=?1023> and it responds by sending back the image kept under name '1023'.

The application is used for image cropping, so after an ajax request to crop the image, it is changed as content on the server but keeps its original name. In order to see the result of the cropping, after the ajax request has been completed, the first image is removed from the DOM and a new image is inserted with the same name <img src=?1023>.

To avoid cashing I add to the request the "time" tag prepended with "#" so it becomes like <img src=?1023#1467294764124>. The server automatically filters out the hash part of the request and responds correctly by sending back my image kept as '1023'. Thus I always get the last version of the image without much server-side decoding.

1

If you need a refresh of the exact URL and your browser has the image cached, you can use AJAX and a request header to force your browser to download a new copy (even if it isn't stale yet). Here's how you'd do that:

var img = $("#myimg");
var url = img.attr("src");
$.ajax({
    url: url,
    headers: { "Cache-Control": "no-cache" }
}).done(function(){
    // Refresh is complete, assign the image again
    img.attr("src", url);
});

Nothing else worked for me because while appending a token to the query string would download the new image, it didn't invalidate the image in the cache at the old URL so future requests would continue to show the old image. The old URL is the only one sent to the browser, and the server was directing the client to cache the image for longer than it should.

If this still doesn't refresh the image for you, see if this answer helps. For more information, here is documentation on the Cache-Control request header.

Pluto
  • 2,900
  • 27
  • 38
  • THANK YOU! ACTUAL ANSWER OVER HERE PEOPLE! Adding timestamps is fine, but then you need to do it on EVERY INSTANCE OF THE IMAGE. If someone uploads a new avatar, I want it to be updated everywhere, not just on the avatar screen where there's a timestamp. Doing ?refresh=timestamp means it's a different cache, so when they go back to the homepage it's stale again. This is the real answer, refresh their cache and never use timestamps – jerclarke Jun 22 '23 at 22:11
0

Based on @kasper Taeymans' answer.

If u simply need reload image (not replace it's src with smth new), try:

$(function() {
  var img = $('#img');

  var refreshImg = function(img) {
    // the core of answer is 2 lines below
    var dummy = '?dummy=';
    img.attr('src', img.attr('src').split(dummy)[0] + dummy + (new Date()).getTime());

    // remove call on production
    updateImgVisualizer();
  };


  // for display current img url in input
  // for sandbox only!
  var updateImgVisualizer = function() {
    $('#img-url').val(img.attr('src'));
  };

  // bind img reload on btn click
  $('.img-reloader').click(function() {
    refreshImg(img);
  });

  // remove call on production
  updateImgVisualizer();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<img id="img" src="http://dummyimage.com/628x150/">


<p>
  <label>
    Current url of img:
    <input id="img-url" type="text" readonly style="width:500px">
  </label>
</p>

<p>
  <button class="img-reloader">Refresh</button>
</p>
userlond
  • 3,632
  • 2
  • 36
  • 53
0

I may have to reload the image source several times. I found a solution with Lodash that works well for me:

$("#myimg").attr('src', _.split($("#myimg").attr('src'), '?', 1)[0] + '?t=' + _.now());

An existing timestamp will be truncated and replaced with a new one.

slp
  • 376
  • 3
  • 5
0

In the html:

foreach (var item in images) {
   <Img src="@Url.Content(item.ImageUrl+"?"+DateTime.Now)" > 
}
ouflak
  • 2,458
  • 10
  • 44
  • 49
  • 1
    This question is about client-side requesting to reload an image from server, using jQuery (or maybe native ECMAScript). Your answer, although valid, is using a different language – DanielCuadra Jan 19 '22 at 16:10
-2

I simply do this in html:

<script>
    $(document).load(function () {
        d = new Date();
        $('#<%= imgpreview.ClientID %>').attr('src','');
    });
</script>

And reload the image in code behind like this:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        image.Src = "/image.jpg"; //url caming from database
    }

}

FTheGodfather
  • 902
  • 7
  • 6