Jak ponownie załadować / odświeżyć element (obraz) w jQuery

262

Czy jest możliwe ponowne załadowanie obrazu o identycznej nazwie pliku z serwera za pomocą jQuery?

Na przykład mam obraz na stronie, jednak obraz fizyczny może się zmienić w zależności od działań użytkownika. Uwaga: nie oznacza to zmiany nazwy pliku, ale sam plik.

to znaczy:

  • Użytkownik wyświetla obraz na stronie domyślnej
  • Użytkownik przesyła nowy obraz
  • Domyślny obraz na stronie nie zmienia się (zakładam, że wynika to z identyczności nazwy pliku, przeglądarka używa wersji buforowanej)

Ten sam problem występuje bez względu na to, jak często wywoływany jest poniższy kod.

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

W dokumentacji jQuery funkcja „load” byłaby idealna, gdyby miała domyślną metodę odpalenia zdarzenia, w przeciwieństwie do powiązania funkcji zwrotnej z udanym / całkowitym załadowaniem elementu.

Każda pomoc jest mile widziana.

Alexis Abril
źródło
1
@Alexis, czy masz problem z tym, że obraz jest buforowany w przeglądarce i nie aktualizuje się po zmianie na serwerze?
sójka
1
@jeerose, uważam, że jest to problem, ponieważ plik faktycznie się zmienia (ta sama nazwa pliku) i jest odzwierciedlany na stronie, jeśli wykonasz pełne odświeżenie strony.
Alexis Abril

Odpowiedzi:

551

Wygląda na to, że przeglądarka buforuje obraz (co teraz zauważam, że napisałeś w swoim pytaniu). Możesz zmusić przeglądarkę do ponownego załadowania obrazu, przekazując dodatkową zmienną, taką jak:

d = new Date();
$("#myimg").attr("src", "/myimg.jpg?"+d.getTime());
sójka
źródło
1
Dodanie zmiennej ciągu zapytania całkowicie przeszło mi przez myśl. To rozwiązało problem, a obraz ładuje się ponownie na żądanie.
Alexis Abril
45
wskazówka gangsta, uwielbiam to
Dave Jellison
4
Działa i jest to miłe obejście, ale wciąż obejście! Czy nie ma innego sposobu pobierania obrazu, który każe przeglądarce zapomnieć o pamięci podręcznej?
spuas
Mam naprawdę wybredną kamerę internetową, która wydaje się zabraniać wszelkich próśb o obrazy statyczne zawierające parametry. Ugh. W przeciwnym razie jest to świetne rozwiązanie.
dangowans
3
@TomasGonzalez B / c tam jest szansa na uzyskanie kolizji z random, i nie powinien nigdy być z Datechyba że jesteś naprawdę bardzo szybko. ; ^) Ustalenie daty na kliencie nie wymaga tak dużych zasobów, i możesz ponownie użyć tyle obrazów, ile potrzebujesz, aby pobrać jednocześnie, więc przejdź do kroku 4. Zysk.
ruffin
57

Prawdopodobnie nie jest to najlepszy sposób, ale w przeszłości rozwiązałem ten problem, po prostu dodając znacznik czasu do adresu URL obrazu za pomocą JavaScript:

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

Następnym razem, gdy się ładuje, znacznik czasu jest ustawiany na bieżącą godzinę, a adres URL jest inny, więc przeglądarka wykonuje GET dla obrazu zamiast używać wersji z pamięci podręcznej.

Kaleb Brasee
źródło
2
Działa to dla mnie przez lata, ale dziś mój serwer obrazów (nie kontrolowany przeze mnie) zaczął zwracać uszkodzony link, jeśli nazwa pliku nie jest dokładna. Jeśli ktoś ma inne obejście, byłoby to bardzo mile widziane. Niestety każda odpowiedź w tym wątku jest odmianą tego.
felwithe
@felwithe, może ten serwer szuka rozszerzenia tylko na końcu zapytania? Możesz więc spróbować przetestować to podejście: imagename.jpg?t=1234567&q=.jpglubimagename.jpg#t1234567.jpg
FlameStorm
26

Może to być jeden z dwóch problemów, o których sam wspominasz.

  1. Serwer buforuje obraz
  2. JQuery nie uruchamia się lub przynajmniej nie aktualizuje atrybutu

Szczerze mówiąc, myślę, że to numer dwa. Byłoby o wiele łatwiej, gdybyśmy mogli zobaczyć więcej jQuery. Ale na początek spróbuj najpierw usunąć atrybut, a następnie ustaw go ponownie. Aby zobaczyć, czy to pomaga:

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

Nawet jeśli to działa, opublikuj kod, ponieważ nie jest to optymalne, imo :-)

Kordonme
źródło
@Kordonme, czy to tutaj ktoś komentuje „złe” jQuery? (Żartuję, żartuję);)
jay
@Kordonme, tak naprawdę odbywa się to w module obsługi zdarzeń i w tej chwili jest to jedyny wiersz kodu. Dodałem alert tuż przed tym wierszem, aby sprawdzić, czy zdarzenie faktycznie się uruchamia. Zdarzenie jest uruchamiane bez błędów.
Alexis Abril
3
Mam naprawdę wybredną kamerę internetową, która wydaje się zabraniać wszelkich próśb o obrazy statyczne zawierające parametry. Ugh. To świetne rozwiązanie dla mojego wyjątkowego przypadku. Dzięki.
dangowans
To najlepsza odpowiedź, jeśli nie chcesz / potrzebujesz parametrów rezydualnych
RafaSashi,
Dzięki temu pomogłem (buforowałem to tylko dla mnie w Chrome)
Daniel Resch,
14

z jednym wierszem bez obawy o zakodowanie na stałe obrazu src w javascript (dzięki jeerose za pomysły:

$("#myimg").attr("src", $("#myimg").attr("src")+"?timestamp=" + new Date().getTime());
Radu
źródło
13
Bądź ostrożny, ponieważ spowoduje to nieskończone dodawanie coraz większej liczby znaków na końcu adresu URL
Alfo
9

Aby ominąć buforowanie i uniknąć dodawania nieskończonych znaczników czasu do adresu URL obrazu, usuń poprzedni znacznik czasu przed dodaniem nowego, oto jak to zrobiłem.

//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);
}
zerwać
źródło
6

To działa świetnie! jednak jeśli przeładujesz src wiele razy, znacznik czasu zostanie również połączony z adresem URL. Zmodyfikowałem zaakceptowaną odpowiedź, aby sobie z tym poradzić.

$('#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());
});
kasper Taeymans
źródło
3

Czy próbowałeś zresetować html kontenerów obrazów. Oczywiście, jeśli buforuje to przeglądarka, to nie pomogłoby.

function imageUploadComplete () {
    $("#image_container").html("<img src='" + newImageUrl + "'>");
}
Matti Lyra
źródło
2

Czasami rozwiązanie takie jak -

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

też nie odświeżam src poprawnie, wypróbuj to, to zadziałało dla mnie ->

$("#Image").attr("src", "dummy.jpg");
$("#Image").attr("src", $('#srcVal').val()+"&"+Math.floor(Math.random()*1000));
Kulbhushan Chaskar
źródło
1

Przydatne może być użycie „#” jako separatora

Moje obrazy są przechowywane w „ukrytym” folderze powyżej „www”, aby tylko zalogowani użytkownicy mieli do nich dostęp. Z tego powodu nie mogę użyć zwykłego, <img src=/somefolder/1023.jpg>ale wysyłam żądania do serwera w podobny sposób, <img src=?1023>a on odpowiada, wysyłając z powrotem obraz o nazwie „1023”.

Aplikacja służy do kadrowania obrazu, więc po żądaniu ajax do przycięcia obrazu, zostaje zmieniona jako zawartość na serwerze, ale zachowuje swoją oryginalną nazwę. Aby zobaczyć wynik przycinania, po zakończeniu żądania ajax, pierwszy obraz jest usuwany z DOM i wstawiany jest nowy obraz o tej samej nazwie <img src=?1023>.

Aby uniknąć wypłaty gotówki, dodaję do żądania tag „time” poprzedzony „#”, aby stał się podobny <img src=?1023#1467294764124>. Serwer automatycznie odfiltrowuje część skrótu żądania i odpowiada poprawnie, wysyłając z powrotem mój obraz zachowany jako „1023”. Dlatego zawsze otrzymuję ostatnią wersję obrazu bez większego dekodowania po stronie serwera.

użytkownik3506298
źródło
1
Po co męczyć się z tym, aby pokazać obraz? Wygląda na bezsensowny kłopot
lucasreta,
0

Być może będę musiał ponownie załadować źródło obrazu kilka razy. Znalazłem rozwiązanie z Lodash, które działa dobrze dla mnie:

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

Istniejący znacznik czasu zostanie obcięty i zastąpiony nowym.

slp
źródło
-1

Na podstawie odpowiedzi @kasper Taeymans.

Jeśli po prostu potrzebujesz przeładować obraz (nie zastępuj jego pliku src nowym smth), spróbuj:

$(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
źródło
-2

Po prostu robię to w html:

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

I ponownie załaduj obraz w kodzie z tyłu w następujący sposób:

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

}

FTheGodfather
źródło
1
Ponowne ładowanie strony i ustawienie w asp.NET WebForms tak naprawdę nie jest na ten temat.
Jonas Stensved