如何在jQuery中重新加载/刷新元素(图像)

270

是否有可能使用jQuery从服务器重新加载具有相同文件名的图像?

例如,我在页面上有一张图片,但实际的图像可以根据用户操作而改变。请注意,这并不意味着文件名会更改,而是实际的文件本身会发生更改。

即:

  • 用户在默认页面上查看图像
  • 用户上传新图片
  • 页面上的默认图像不会更改(我认为这是因为文件名相同,浏览器使用缓存版本)

无论多少次调用下面的代码,都会出现相同的问题。

$("#myimg").attr("src", "/myimg.jpg");
在jQuery文档中,"load"函数将会更完美,如果它有一个默认的方式来触发事件,而不是绑定回调函数到元素成功/完成加载。任何帮助都将不胜感激。

1
@Alexis,你的问题是图片在浏览器中被缓存了,在服务器上更改后不会更新吗? - jay
1
@jeerose,我认为问题就在这里,因为如果您进行完整页面刷新,文件实际上会更改(相同的文件名),并反映在页面上。 - Alexis Abril
14个回答

574

看起来是你的浏览器缓存了这张图片(我现在注意到你在问题中提到了它)。你可以通过传递一个额外的变量来强制浏览器重新加载该图片,方法如下:

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

1
完全忘记了添加查询字符串变量。这个解决了问题,现在图像可以重新加载请求了。 - Alexis Abril
4
它可以工作,并且是一个不错的解决方法,但仍然只是一个解决方法!是否有其他获取图像的方式,告诉浏览器忘记缓存的图像? - spuas
我有一个非常挑剔的网络摄像头,似乎禁止包含参数的静态图像请求。唉,否则这是一个很好的解决方案。 - dangowans
3
@TomasGonzalez提到,“使用随机数会存在碰撞的风险,而使用Date则不应该,除非你非常非常快。”在客户端获取日期不会占用太多资源,您可以重复使用它来一次性获取所需的多张图像,因此继续执行第4步骤。获利。 - ruffin
1
我在下面发布了一个新的方法,我在任何答案中都找不到它,它会导致浏览器忽略缓存并使用未修改的URL获取新副本。这对我很重要,因为原始URL是Web服务器提供的唯一URL,而此方法在第一次下载后没有帮助。 - Pluto
显示剩余6条评论

58

可能不是最好的方法,但我过去解决这个问题的方式是使用JavaScript将时间戳附加到图像URL上:

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

下次加载时,时间戳会被设置为当前时间,并且URL也会有所不同,这样浏览器就会获取图像的GET请求而不是使用缓存版本。


2
这个方法在我身上运行了多年,但今天我的图像服务器(不受我控制)开始返回一个损坏的链接,如果文件名不是精确的。如果有人有另一种解决方法,那将不胜感激。不幸的是,这个帖子中的每个答案都是这个变体。 - felwithe
@felwithe,也许这个服务器只查找查询结尾的扩展名?因此,您可以尝试测试以下方法:imagename.jpg?t=1234567&q=.jpgimagename.jpg#t1234567.jpg - FlameStorm

28

这可能是你自己提到的两个问题之一。

  1. 服务器正在缓存图像
  2. jQuery没有触发或者至少没有更新属性

老实说,我认为是第二个问题。如果我们能看到更多 jQuery 代码会更容易解决。但是首先可以尝试先删除属性,然后再设置它。只是为了看看是否有所帮助:

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

即使这个方法可行,我认为还是应该贴上代码,因为这不是最优解。


@Kordonme,这是有人评论“糟糕”的jQuery的地方吗?(开玩笑,开玩笑);) - jay
@Kordonme,这实际上是在事件处理程序中进行的,目前这是唯一的代码行。我在这行代码之前添加了一个警报,只是为了验证事件是否真的触发。该事件没有出现错误。 - Alexis Abril
3
我有一个非常挑剔的网络摄像头,似乎禁止包含参数的静态图像请求。唉,这对我的特殊情况是一个很好的解决方案。谢谢。 - dangowans
如果您不想/不需要剩余参数,这是最佳答案。 - RafaSashi
谢谢,这很有帮助(它只在我的Chrome浏览器中缓存了它)。 - user6057915

14

借助 jeerose 的想法,只需一行代码即可解决无需硬编码 JavaScript 中的图像 src 的问题:

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

14
请注意,这会无限地向URL末尾添加更多字符。 - Alfo

9
为了避免缓存和避免在图像网址中添加无限的时间戳,需要在添加新时间戳之前删除先前的时间戳,这是我所做的方式。
//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);
}

6

这很好用!但是如果您多次重新加载src,时间戳也会连接到网址中。我修改了已接受的答案来处理这个问题。

$('#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());
});

3

您尝试过重置图像容器的html吗?当然,如果是浏览器缓存的问题,这样做可能不会有用。

function imageUploadComplete () {
    $("#image_container").html("<img src='" + newImageUrl + "'>");
}

2
如果您需要刷新确切的URL,而您的浏览器已经缓存了该图像,您可以使用AJAX和请求头来强制浏览器下载新副本(即使它还没有过期)。以下是如何实现:
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);
});

对我来说,没有其他方法有效,因为将令牌附加到查询字符串中会下载新图像,但不会使缓存中旧URL的图像失效,因此未来的请求仍将显示旧图像。只有旧URL被发送到浏览器,并且服务器指示客户端将图像缓存时间延长。

如果这对您来说仍无法刷新图像,请查看此答案是否有帮助。有关更多信息,请参阅Cache-Control请求头的文档


谢谢!真正的答案在这里!添加时间戳是可以的,但你需要在每个图像实例上都这样做。如果有人上传了新的头像,我希望它在任何地方都能更新,而不仅仅是在有时间戳的头像屏幕上。使用?refresh=timestamp意味着它是一个不同的缓存,所以当他们返回到主页时,它又变得陈旧了。这才是真正的答案,刷新他们的缓存,永远不要使用时间戳。 - jerclarke

2
有时候实际上的解决方案是这样的 -
$("#Image").attr("src", $('#srcVal').val()+"&"+Math.floor(Math.random()*1000));

同时也无法正确刷新 src,尝试这个方法,对我有用 ->

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

1

使用"#"作为分隔符可能很有用

我的图片保存在一个位于"www"上方的“隐藏”文件夹中,因此只有已登录用户才能访问它们。因此,我不能使用普通的<img src=/somefolder/1023.jpg>,但我发送请求到服务器,例如<img src=?1023>,它会响应并发送名为'1023'的图片。

该应用程序用于图像裁剪,在向服务器发出ajax请求后,将其更改为服务器上的内容但保持其原始名称。为了查看裁剪结果,在ajax请求完成后,第一张图片将从DOM中删除,并插入具有相同名称的新图片<img src=?1023>

为了避免缓存,我在请求中添加了“时间”标记,以“#”为前缀,因此它变成了这样<img src=?1023#1467294764124>。服务器会自动过滤掉请求的哈希部分,并正确响应发送我的名为'1023'的图片。因此,我始终可以获得最新版本的图像,而无需进行太多的服务器端解码。


1
为什么要费那么大劲去提供一张图片呢?看起来像是一个毫无意义的麻烦。 - lucasreta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接