Uzyskuję dostęp do linku w mojej witrynie, który zapewnia nowy obraz za każdym razem, gdy jest dostępny.
Problem, na który napotykam, polega na tym, że jeśli spróbuję załadować obraz w tle, a następnie zaktualizować ten na stronie, obraz się nie zmieni - chociaż jest aktualizowany po ponownym załadowaniu strony.
var newImage = new Image();
newImage.src = "http://localhost/image.jpg";
function updateImage()
{
if(newImage.complete) {
document.getElementById("theText").src = newImage.src;
newImage = new Image();
number++;
newImage.src = "http://localhost/image/id/image.jpg?time=" + new Date();
}
setTimeout(updateImage, 1000);
}
Nagłówki, jakie widzi FireFox:
HTTP/1.x 200 OK
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: image/jpeg
Expires: Fri, 30 Oct 1998 14:19:41 GMT
Server: Microsoft-HTTPAPI/1.0
Date: Thu, 02 Jul 2009 23:06:04 GMT
Muszę wymusić odświeżenie tylko tego obrazu na stronie. Jakieś pomysły?
javascript
image
url
refresh
QueueHammer
źródło
źródło
Odpowiedzi:
Spróbuj dodać bufor pamięci podręcznej na końcu adresu URL:
Spowoduje to automatyczne dodanie bieżącego znacznika czasu podczas tworzenia obrazu i sprawi, że przeglądarka ponownie wyszuka obraz zamiast pobierać ten z pamięci podręcznej.
źródło
'image.jpg?' + (+new Date())
Date.now()
na toMath.random()
Widziałem wiele różnych odpowiedzi na pytanie, jak to zrobić, więc pomyślałem, że streszczę je tutaj (plus dodaję czwartą metodę mojego wynalazku):
(1) Dodaj unikalny parametr zapytania pomijania pamięci podręcznej do adresu URL, taki jak:
Plusy: 100% niezawodny, szybki i łatwy do zrozumienia i wdrożenia.
Wady: całkowicie pomija buforowanie, co oznacza niepotrzebne opóźnienia i wykorzystanie przepustowości, gdy obraz nie zmienia się między widokami. Potencjalnie zapełni pamięć podręczną przeglądarki (i wszelkie pośrednie pamięci podręczne) wieloma, wieloma kopiami dokładnie tego samego obrazu! Wymaga również modyfikacji adresu URL obrazu.
Kiedy stosować: Użyj, gdy obraz ciągle się zmienia, na przykład w przypadku obrazu z kamery na żywo. Jeśli korzystasz z tej metody, pamiętaj, aby podawać same obrazy z
Cache-control: no-cache
nagłówkami HTTP !!! (Często można to skonfigurować za pomocą pliku .htaccess). W przeciwnym razie będziesz stopniowo zapełniał pamięć podręczną starymi wersjami obrazu!(2) Dodaj parametr zapytania do adresu URL, który zmienia się tylko wtedy, gdy plik się zmienia, np .:
(To jest kod PHP po stronie serwera, ale ważne jest tutaj to, że do nazwy pliku dołączany jest kwerenda ? M = [czas ostatniej modyfikacji pliku]).
Plusy: w 100% niezawodny, szybki i łatwy do zrozumienia i wdrożenia oraz doskonale zachowuje zalety buforowania.
Cons: Wymaga modyfikacji adresu URL obrazu. Trochę więcej pracy dla serwera - musi on uzyskać dostęp do czasu ostatniej modyfikacji pliku. Wymaga również informacji po stronie serwera, więc nie nadaje się do rozwiązania wyłącznie po stronie klienta, aby sprawdzić odświeżony obraz.
Kiedy użyć: Kiedy chcesz buforować obrazy, ale może wymagać aktualizacji od czasu do czasu na serwerze bez zmiany samej nazwy pliku. ORAZ kiedy możesz łatwo upewnić się, że do każdego wystąpienia obrazu w kodzie HTML dodano poprawne zapytanie.
(3) Podawać swoje zdjęcia z nagłówkiem
Cache-control: max-age=0, must-revalidate
i dodać unikatowy memcache -busting fragment identyfikator do adresu URL, takich jak:Chodzi o to, że nagłówek kontroli pamięci podręcznej umieszcza obrazy w pamięci podręcznej przeglądarki, ale natychmiast zaznacza je jako przestarzałe, więc za każdym razem, gdy są ponownie wyświetlane, przeglądarka musi sprawdzić na serwerze, czy się zmieniły. Zapewnia to, że pamięć podręczna HTTP przeglądarki zawsze zwraca najnowszą kopię obrazu. Jednak przeglądarki często używają kopii obrazu w pamięci, jeśli go mają, i nawet nie sprawdzają pamięci podręcznej HTTP w tym przypadku. Aby temu zapobiec, stosuje się identyfikator fragmentu: Porównanie obrazu w pamięci
src
obejmuje identyfikator fragmentu, ale zostaje on usunięty przed zapytaniem o pamięć podręczną HTTP. (Tak więc, na przykład,image.jpg#A
iimage.jpg#B
oba mogą być wyświetlane zimage.jpg
pozycji w pamięci podręcznej HTTP przeglądarki, aleimage.jpg#B
nigdy nie będzie wyświetlany przy użyciu danych obrazu zachowanych w pamięci od czasuimage.jpg#A
ostatniego wyświetlenia).Plusy: Właściwie wykorzystuje mechanizmy buforowania HTTP i używa buforowanych obrazów, jeśli się nie zmieniły. Działa na serwerach, które dławią się kwerendą dodawaną do statycznego adresu URL obrazu (ponieważ serwery nigdy nie widzą identyfikatorów fragmentów - są one wyłącznie na użytek przeglądarki).
Cons: Polega na nieco wątpliwym (lub przynajmniej słabo udokumentowanym) zachowaniu przeglądarek w odniesieniu do obrazów z identyfikatorami fragmentów w ich adresach URL (Jednak przetestowałem to z powodzeniem w FF27, Chrome33 i IE11). Nadal wysyła do serwera żądanie ponownej walidacji dla każdego widoku obrazu, co może być nadmierne, jeśli obrazy zmieniają się rzadko i / lub opóźnienie jest dużym problemem (ponieważ musisz poczekać na odpowiedź na ponowne sprawdzenie poprawności, nawet jeśli obraz w pamięci podręcznej jest nadal dobry) . Wymaga modyfikacji adresów URL obrazów.
Kiedy stosować: Użyj, gdy obrazy mogą się często zmieniać lub wymagają okresowego odświeżania przez klienta bez udziału skryptu po stronie serwera, ale tam, gdzie nadal chcesz korzystać z buforowania. Na przykład odpytywanie kamery internetowej na żywo, która co kilka minut aktualizuje obraz nieregularnie. Alternatywnie, użyj zamiast (1) lub (2), jeśli twój serwer nie pozwala na kwerendy na statycznych adresach URL obrazów.
(4) Wymuś odświeżenie określonego obrazu za pomocą Javascript, najpierw ładując go do ukrytego,
<iframe>
a następnie wywołująclocation.reload(true)
ramkę iframecontentWindow
.Kroki są następujące:
Załaduj obraz do odświeżenia do ukrytego elementu iframe. To tylko krok konfiguracji - w razie potrzeby można to zrobić z dużym wyprzedzeniem. Nie ma nawet znaczenia, czy obraz nie załaduje się na tym etapie!
Po zakończeniu wyczyść wszystkie kopie tego obrazu na swojej stronie (stronach) lub w dowolnym miejscu w dowolnym węźle DOM (nawet poza stroną przechowywaną w zmiennych javascript). Jest to konieczne, ponieważ w przeciwnym razie przeglądarka może wyświetlić obraz z czerstwego kopii w pamięci (IE11 szczególnie robi to): Trzeba zapewnić wszystkim w pamięci kopie są usuwane, zanim orzeźwiający HTTP cache. Jeśli inny kod javascript działa asynchronicznie, być może trzeba będzie w międzyczasie uniemożliwić temu kodowi tworzenie nowych kopii obrazu, który ma zostać odświeżony.
Zadzwoń
iframe.contentWindow.location.reload(true)
. Tetrue
siły obejście cache, przeładunek bezpośrednio z serwera i nadpisania istniejącej kopii buforowane.Po zakończeniu ponownego ładowania przywróć puste obrazy. Powinny teraz wyświetlać nową wersję z serwera!
W przypadku obrazów z tej samej domeny możesz załadować obraz bezpośrednio do iframe. W przypadku obrazów między domenami należy zamiast tego załadować stronę HTML z domeny zawierającą obraz w
<img>
tagu, w przeciwnym razie podczas próby połączenia zostanie wyświetlony błąd „Odmowa dostępu”iframe.contentWindow.reload(...)
.Plusy: Działa tak jak funkcja image.reload (), którą chciałbyś, aby DOM miał! Pozwala na normalne buforowanie obrazów (nawet z przyszłymi datami ważności, jeśli chcesz, co pozwala uniknąć częstego przedłużania ważności). Umożliwia odświeżenie określonego obrazu bez zmiany adresów URL tego obrazu na bieżącej stronie lub na innych stronach, przy użyciu tylko kodu po stronie klienta.
Minusy: opiera się na JavaScript. Nie gwarantujemy 100% poprawnego działania w każdej przeglądarce (przetestowałem to z powodzeniem w FF27, Chrome33 i IE11). Bardzo skomplikowane w stosunku do innych metod.
Kiedy używać: Gdy masz kolekcję zasadniczo statycznych obrazów, które chcesz buforować, ale nadal musisz mieć możliwość ich okresowej aktualizacji i natychmiastowej wizualnej informacji zwrotnej, że aktualizacja miała miejsce. (Zwłaszcza gdy odświeżanie całej strony przeglądarki nie działa, jak w niektórych aplikacjach internetowych opartych na AJAX na przykład). A gdy metody (1) - (3) są niewykonalne, ponieważ (z jakiegokolwiek powodu) nie można zmienić wszystkich adresów URL, które mogą potencjalnie wyświetlać obraz, który należy zaktualizować. (Zauważ, że przy użyciu tych 3 metod obraz zostanie odświeżony, ale jeśli inna strona następnie spróbuje wyświetlić ten obraz bez odpowiedniego zapytania lub identyfikatora fragmentu, może zamiast tego wyświetlić starszą wersję).
Szczegóły implementacji tego w dość solidny i elastyczny sposób podano poniżej:
Załóżmy, że twoja strona zawiera pusty 1x1 piksel .gif w ścieżce URL
/img/1x1blank.gif
, a także ma następujący jednowierszowy skrypt PHP (wymagany tylko do zastosowania wymuszonego odświeżania obrazów między domenami i może być przepisany w dowolnym języku skryptowym po stronie serwera , oczywiście) w ścieżce URL/echoimg.php
:Oto realistyczna implementacja tego, jak możesz to wszystko zrobić w JavaScript. Wygląda to trochę skomplikowane, ale jest wiele komentarzy, a ważną funkcją jest po prostu forceImgReload () - pierwsze dwa tylko puste i niepuste obrazy, i powinny być zaprojektowane do wydajnej pracy z własnym HTML, więc koduj je jako działa najlepiej dla ciebie; wiele z ich komplikacji może być niepotrzebnych dla Twojej witryny:
Następnie, aby wymusić odświeżenie obrazu znajdującego się w tej samej domenie co strona, możesz po prostu:
Aby odświeżyć obraz z innego miejsca (między domenami):
Bardziej zaawansowaną aplikacją może być przeładowanie obrazu po przesłaniu nowej wersji na serwer, przygotowanie wstępnego etapu procesu przeładowania jednocześnie z przesyłaniem, aby zminimalizować widoczne opóźnienie przeładowania dla użytkownika. Jeśli przesyłasz za pośrednictwem AJAX, a serwer zwraca bardzo prostą tablicę JSON [sukces, szerokość, wysokość], wówczas twój kod może wyglądać mniej więcej tak:
Ostatnia uwaga: chociaż ten temat dotyczy obrazów, potencjalnie dotyczy również innych rodzajów plików lub zasobów. Na przykład zapobieganie używaniu przestarzałych plików skryptów lub plików css, a może nawet odświeżanie zaktualizowanych dokumentów PDF (przy użyciu (4) tylko w przypadku skonfigurowania do otwierania w przeglądarce). W takich przypadkach metoda (4) może wymagać pewnych zmian w powyższym javascript.
źródło
image.jpg#123
Naimage.jpg#124
(lub cokolwiek innego, o ile bit po „#” się zmieni). Czy możesz wyjaśnić, co to jest przeładowywanie i dlaczego?contentWindow
pomocą javascript, aby wykonaćreload(true)
wywołanie, które jest krytyczną częścią metody ... więc nie, metoda (4 ) nie będzie działać w przypadku treści między domenami. Dobrze zauważony; Zaktualizuję „Wady”, aby to uwzględnić.Jako alternatywa dla ...
...wygląda na to że...
... wystarczy oszukać pamięć podręczną przeglądarki bez omijania pamięci podręcznej w górę, zakładając, że zwróciłeś prawidłowe
Cache-Control
nagłówki. Chociaż możesz użyć ...... tracisz korzyści z nagłówków
If-Modified-Since
lubIf-None-Match
, więc coś w stylu ...... powinien uniemożliwić przeglądarce ponowne pobranie całego obrazu, jeśli tak naprawdę nie zmienił się. Testowane i działające na IE, Firefox i Chrome. Irytujące, że zawiedzie w Safari, chyba że użyjesz ...
... chociaż nadal może to być lepsze niż zapełnianie pamięci podręcznej setkami identycznych obrazów, szczególnie gdy działają one na twoim serwerze. ;-)
Aktualizacja (28.09.2014): Obecnie wygląda na to, że
Cache-Control: no-store
jest także potrzebny w Chrome.źródło
src
atrybut, więc dodanie unikalnego identyfikatora fragmentu gwarantuje, że obraz nie zostanie po prostu pobrany z pamięci. Ale identyfikatory fragmentów nie są wysyłane jako część żądań HTTP, więc zwykła pamięć podręczna HTTP będzie używana jak zwykle. Właśnie dlatego ta technika działa.Cache-Control: max-age=0, must-revalidate
jest dla mnie dobre?newImage.src = "http://localhost/image.jpg#" + i++;
Czy po utworzeniu nowego obrazu usuwasz stary obraz z DOM i zastępujesz go nowym?
Możesz pobierać nowe obrazy przy każdej aktualizacji obrazu, ale nie dodawać ich do strony.
Można to zrobić na wiele sposobów. Coś takiego działałoby.
Po uruchomieniu tej funkcji, jeśli nadal występują problemy, prawdopodobnie jest to problem buforowania, o którym mówią inne odpowiedzi.
źródło
Jedną z odpowiedzi jest hackerskie dodanie parametru pobierania zapytania, jak sugerowano.
Lepszą odpowiedzią jest wyemitowanie kilku dodatkowych opcji w nagłówku HTTP.
Podając datę w przeszłości, przeglądarka nie będzie jej buforować.
Cache-Control
został dodany w HTTP / 1.1, a znacznik, który należy ponownie zweryfikować, wskazuje, że serwery proxy nigdy nie powinny obsługiwać starego obrazu, nawet w łagodzących okolicznościach, iPragma: no-cache
nie jest tak naprawdę konieczne w obecnych współczesnych przeglądarkach / pamięciach podręcznych, ale może pomóc w niektórych chrupiących, uszkodzonych starych implementacjach.źródło
Miałem wymaganie: 1) nie mogę dodać żadnego
?var=xx
do obrazu 2) powinien działać między domenamiNaprawdę podoba mi się opcja nr 4 w tej odpowiedzi z jednym, ale:
Mój szybki i brudny sposób to:
iframe.contentWindow.location.reload(true);
Oto jest
Tak, wiem, setTimeout ... Musisz to zmienić na odpowiednie zdarzenia onload.
źródło
Następnie poniżej w javascript
I tak to się dzieje, gdy obraz się ładuje, planuje jego ponowne załadowanie w ciągu 1 sekundy. Używam tego na stronie z kamerami domowymi różnego typu.
źródło
Skończyło się na tym, że serwer zmapował każde żądanie obrazu w tym katalogu do źródła, które próbowałem zaktualizować. Następnie mój licznik dopisał numer na końcu nazwy, aby DOM mógł zobaczyć go jako nowy obraz i załadować.
Na przykład
zażąda tego samego kodu generowania obrazu, ale będzie wyglądał jak inne obrazy w przeglądarce.
źródło
źródło
../showImage.phpFri May 01 2015 17:34:18 GMT+0200 (Mitteleuropäische Sommerzeit)
to była poprawna nazwa pliku ... Przynajmniej tak próbuje się załadować ...path='../showImage.php';
napath='../showImage.php?';
ustaw własny src jako src.
źródło
Spróbuj użyć bezwartościowego zapytania, aby uczynić go unikalnym adresem URL:
źródło
Poniższy przykład, oparty na kodzie Doina nr 4, znacznie upraszcza ten kod,
document.write
zamiast wykorzystywaćsrc
goiframe
do obsługi CORS. Skupia się tylko na usuwaniu pamięci podręcznej przeglądarki, a nie ponownym ładowaniu każdego obrazu na stronie.Poniżej jest napisane
typescript
i korzysta z bibliotekiangular
$ q promise, po prostu fyi, ale powinno być wystarczająco łatwe do przeniesienia na javascript waniliowy. Metoda ma żyć w klasie maszynopisu.Zwraca obietnicę, która zostanie rozwiązana po zakończeniu ładowania ramki iframe. Nie bardzo przetestowany, ale działa dobrze dla nas.
źródło
+ encodeURI(src) +
aby poprawnie uciecsrc
wiframe
.Poniższy kod jest przydatny do odświeżenia obrazu po kliknięciu przycisku.
źródło
Rozwiązałem ten problem, wysyłając dane z powrotem przez serwlet.
Następnie ze strony podajesz serwletowi kilka parametrów, aby pobrać poprawny plik obrazu.
źródło
Oto moje rozwiązanie. To jest bardzo proste. Planowanie ramek może być lepsze.
źródło
Nie potrzeba
new Date().getTime()
shenaniganów. Możesz oszukać przeglądarkę, mając niewidoczny obraz-sztuczkę i używając jQuery .load (), a następnie tworząc nowy obraz za każdym razem:źródło
Proste rozwiązanie: dodaj ten nagłówek do odpowiedzi:
Dlaczego to działa, zostało jasno wyjaśnione na tej wiarygodnej stronie: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
Wyjaśnia również, dlaczego
no-cache
nie działa.Inne odpowiedzi nie działają, ponieważ:
Caching.delete
dotyczy nowej pamięci podręcznej, którą możesz utworzyć do pracy offline, patrz: https://web.dev/cache-api-quick-guide/Fragmenty używające # w adresie URL nie działają, ponieważ # informuje przeglądarkę, aby nie wysyłała żądania do serwera.
Buster-custer z losową częścią dodaną do adresu działa, ale również zapełni pamięć podręczną przeglądarki. W mojej aplikacji chciałem pobierać obraz 5 MB co kilka sekund z kamery internetowej. Całkowite zamrożenie komputera zajmie tylko godzinę. Nadal nie wiem, dlaczego pamięć podręczna przeglądarki nie jest ograniczona do rozsądnego maksimum, ale jest to zdecydowanie wada.
źródło
Poprawiłem skrypt z AlexMA do wyświetlania mojej kamery internetowej na stronie internetowej, która okresowo przesyła nowy obraz o tej samej nazwie. Miałem problemy z tym, że czasami obraz migotał z powodu uszkodzonego obrazu lub niepełnego (w górę) załadowanego obrazu. Aby zapobiec migotaniu, sprawdzam naturalną wysokość obrazu, ponieważ rozmiar obrazu z mojej kamery internetowej nie zmienił się. Tylko jeśli załadowana wysokość obrazu odpowiada pierwotnej wysokości obrazu, pełny obraz zostanie wyświetlony na stronie.
źródło
Zastosowałem poniższą koncepcję pierwszego wiązania obrazu fałszywym (buforowym) adresem URL, a następnie powiązania go z prawidłowym adresem URL.
W ten sposób wymuszam odświeżenie przeglądarki przy użyciu prawidłowego adresu URL.
źródło