Actualiser l'image avec une nouvelle à la même url
J'accède à un lien sur mon site qui fournira une nouvelle image chaque fois qu'il est consulté.
Le problème que je rencontre est que si j'essaie de charger l'image en arrière-plan, puis de mettre à jour celle de la page, l'image ne change pas-bien qu'elle soit mise à jour lorsque je recharge la page.
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);
}
En-têtes comme FireFox les voit:
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
Je dois forcer une actualisation de cette image sur la page. Des idées?
16 réponses
Essayez d'ajouter un cache-cache à la fin de l'url:
newImage.src = "http://localhost/image.jpg?" + new Date().getTime();
Cela ajoutera automatiquement l'horodatage actuel lorsque vous créez l'image, et cela fera que le navigateur cherchera à nouveau l'image au lieu de récupérer celle du cache.
J'ai vu beaucoup de variations dans les réponses pour savoir comment faire cela, alors j'ai pensé les résumer ici (en plus d'ajouter une 4ème méthode de ma propre invention):
(1) Ajoutez un paramètre de requête unique de suppression de cache à L'URL, tel que:
newImage.src = "image.jpg?t=" + new Date().getTime();
Avantages: 100% fiable, rapide et facile à comprendre et à mettre en œuvre.
Inconvénients: contourne complètement la mise en cache, ce qui signifie des retards inutiles et une utilisation de la bande passante chaque fois que l'image ne change pas entre vue. Remplira potentiellement le cache du navigateur (et les caches intermédiaires) avec beaucoup, beaucoup de copies d'exactement la même image! En outre, nécessite la modification de L'URL de l'image.
Quand utiliser: utiliser lorsque l'image change constamment, comme pour un flux webcam en direct. Si vous utilisez cette méthode, assurez-vous de servir les images elles-mêmes avec les en-têtes HTTP Cache-control: no-cache
!!! (souvent, cela peut être configuré en utilisant un .fichier htaccess). Sinon, vous remplirez progressivement les caches avec d'anciennes versions de l'image!
(2) Ajouter un paramètre de requête à L'URL qui ne change que lorsque le fichier le fait, par exemple:
echo '<img src="image.jpg?m=' . filemtime('image.jpg') . '">';
(c'est du code côté serveur PHP, mais le point important ici est juste que a ?m = [dernière modification du fichier] la chaîne de requête est ajoutée au nom du fichier).
Avantages: 100% fiable, rapide et facile à comprendre et à mettre en œuvre, et préserve parfaitement les avantages de la mise en cache.
Inconvénients: nécessite de modifier l'URL de l'image. En outre, un peu plus de travail pour le serveur-il doit avoir accès au fichier-dernière modification. En outre, nécessite des informations côté serveur, donc ne convient pas à une solution purement côté client pour vérifier une image actualisée.
Quand utiliser: lorsque vous voulez mettre en cache des images, mais que vous devrez peut-être les mettre à jour à la fin du serveur de temps en temps sans changer le nom de fichier lui-même. Et quand vous pouvez facilement vous assurer que le querystring correct est ajouté à chaque instance d'image dans votre HTML.
(3) servez vos images avec l'en-tête Cache-control: max-age=0, must-revalidate
, et ajoutez un identifiant de fragment uniquememcache -busting à L'URL, tel que:
newImage.src = "image.jpg#" + new Date().getTime();
L'idée ici est que l'en-tête cache-control place les images dans le cache du navigateur, mais les marque immédiatement, de sorte que chaque fois qu'elles sont affichées à nouveau, le navigateur doit vérifier avec le serveur pour voir si elles ont changé. Cela garantit que le cache HTTP du navigateur renvoie toujours la dernière copie du image. Cependant, les navigateurs réutilisent souvent une copie en mémoire d'une image s'ils en ont une, et ne vérifient même pas leur cache HTTP dans ce cas. Pour éviter cela, un identificateur de fragment est utilisé: la comparaison de l'image en mémoire src
inclut l'Identificateur de fragment, mais il est supprimé avant d'interroger le cache HTTP. (Ainsi, par exemple, image.jpg#A
et image.jpg#B
pourraient tous deux être affichés à partir de l'entrée image.jpg
dans le cache HTTP du navigateur, mais image.jpg#B
ne serait jamais affiché en utilisant des données d'image conservées en mémoire à partir du moment où image.jpg#A
a été affiché pour la dernière fois).
Avantages: utilise correctement les mécanismes de mise en cache HTTP, et utilise des images mises en cache si elles n'ont pas changé. Fonctionne pour les serveurs qui s'étouffent sur une chaîne de requête ajoutée à une URL d'image statique (puisque les serveurs ne voient jamais d'identificateurs de fragment - ils sont destinés uniquement aux navigateurs).
Inconvénients: repose sur un comportement quelque peu douteux (ou du moins mal documenté) des navigateurs, en ce qui concerne les images avec des identifiants de fragment dans leurs URL (Cependant, j'ai testé cela avec succès dans FF27, Chrome33 et IE11). Envoie toujours une demande de revalidation au serveur pour chaque vue d'image, ce qui peut être exagéré si les images ne changent que rarement et/ou la latence est un gros problème (puisque vous devez attendre la réponse de revalidation même lorsque l'image mise en cache est toujours bonne). Nécessite la modification des URL d'image.
Quand utiliser: utiliser lorsque les images peuvent changer fréquemment, ou doivent être rafraîchies par intermittence par le client sans implication de script côté serveur, mais où vous voulez toujours l'avantage de la mise en cache. Par exemple, interroger une webcam en direct qui met à jour une image irrégulièrement toutes les quelques minutes. Vous pouvez également utiliser instead of (1) ou (2) si votre serveur n'autorise pas les chaînes de requête sur les URL d'image statiques.
(4) actualisez de force une image particulière en utilisant Javascript, en la chargeant d'abord dans un <iframe>
caché, puis en appelant location.reload(true)
sur contentWindow
de l'iframe.
Les étapes sont:
Chargez l'image à actualiser dans un iframe caché. Ceci est juste une étape de configuration-il peut être fait longtemps à l'avance l'actualisation réelle, si vous le souhaitez. Il n'a même pas d'importance si l'image ne parvient pas à charger à ce stade!
Une fois cela fait, effacez toutes les copies de cette image sur votre(Vos) page (S) ou n'importe où dans n'importe quel nœud DOM (même hors page stockées dans des variables javascript). Ceci est nécessaire car le navigateur peut sinon afficher l'image à partir d'un copie en mémoire périmée (IE11 le fait particulièrement): vous devez vous assurer que toutes les copies en mémoire sont effacées, avant d'actualiser le cache HTTP. Si un autre code javascript s'exécute de manière asynchrone, vous devrez peut-être également empêcher ce code de créer de nouvelles copies de l'image à actualiser entre-temps.
Appel de
iframe.contentWindow.location.reload(true)
. Letrue
force un contournement de cache, rechargeant directement à partir du serveur et écrasant la copie mise en cache existante.Une fois que c'est terminé re - chargement, restaurer les images masquées. Ils devraient maintenant afficher la nouvelle version du serveur!
Pour les images de même domaine, vous pouvez charger l'image directement dans l'iframe. Pour les images inter-domaines, vous devez charger à la place une page HTML de votre domaine {[38] } qui contient l'image dans une balise <img>
, sinon vous obtiendrez une erreur "Accès refusé" en essayant d'appeler iframe.contentWindow.reload(...)
.
Avantages: Fonctionne comme l'image.recharger() fonction que vous souhaitez le DOM avait! Permet aux images de mettre en cache normalement (même avec des dates d'expiration futures si vous le souhaitez, évitant ainsi une revalidation fréquente). Vous permet d'actualiser une image particulière sans modifier les URL de cette image sur la page en cours ou sur d'autres pages, en utilisant uniquement du code côté client.
Inconvénients: repose sur Javascript. Pas 100% garanti pour fonctionner correctement dans tous les navigateurs (j'ai testé cela avec succès dans FF27, Chrome33 et IE11 bien). Très compliqué par rapport aux autres méthodes.
Quand utiliser: lorsque vous avez une collection d'images essentiellement statiques que vous souhaitez mettre en cache, mais que vous devez toujours pouvoir les mettre à jour occasionnellement et obtenir un retour visuel immédiat que la mise à jour a eu lieu. (Surtout quand juste rafraîchir toute la page du navigateur ne fonctionnerait pas, comme dans certaines applications web construites sur AJAX par exemple). Et quand les méthodes (1)-(3) ne sont pas réalisables parce que (pour une raison quelconque) vous ne pouvez pas modifiez toutes les URL qui pourraient potentiellement afficher l'image que vous devez avoir mise à jour. (Notez qu'en utilisant ces 3 méthodes, l'image sera actualisée, mais si une autre page essaie ensuite d'afficher cette image sans l'identifiant querystring ou fragment approprié, il peut afficher une version plus ancienne à la place).
Les détails de la mise en œuvre de cette manière robuste et flexible sont donnés ci-dessous:
Supposons que votre site web contient un pixel vierge 1x1 .GIF sur le chemin D'URL /img/1x1blank.gif
, et a également le script PHP d'une ligne suivant (uniquement requis pour appliquer l'actualisation forcée aux imagescross-domain , et peut être réécrit dans n'importe quel langage de script côté serveur, bien sûr) sur le chemin D'URL /echoimg.php
:
<img src="<?=htmlspecialchars(@$_GET['src'],ENT_COMPAT|ENT_HTML5,'UTF-8')?>">
Ensuite, voici une implémentation réaliste de la façon dont vous pourriez faire tout cela en Javascript. Cela semble un peu compliqué, mais il y a beaucoup de commentaires, et la fonction importante est juste forceImgReload () - les deux premiers sont vides et un-blank images, et devrait être conçu pour fonctionner efficacement avec votre propre HTML, afin de les coder comme fonctionne le mieux pour vous; une grande partie des complications en eux peuvent être inutiles pour votre site web:
// This function should blank all images that have a matching src, by changing their src property to /img/1x1blank.gif.
// ##### You should code the actual contents of this function according to your page design, and what images there are on them!!! #####
// Optionally it may return an array (or other collection or data structure) of those images affected.
// This can be used by imgReloadRestore() to restore them later, if that's an efficient way of doing it (otherwise, you don't need to return anything).
// NOTE that the src argument here is just passed on from forceImgReload(), and MAY be a relative URI;
// However, be aware that if you're reading the src property of an <img> DOM object, you'll always get back a fully-qualified URI,
// even if the src attribute was a relative one in the original HTML. So watch out if trying to compare the two!
// NOTE that if your page design makes it more efficient to obtain (say) an image id or list of ids (of identical images) *first*, and only then get the image src,
// you can pass this id or list data to forceImgReload() along with (or instead of) a src argument: just add an extra or replacement parameter for this information to
// this function, to imgReloadRestore(), to forceImgReload(), and to the anonymous function returned by forceImgReload() (and make it overwrite the earlier parameter variable from forceImgReload() if truthy), as appropriate.
function imgReloadBlank(src)
{
// ##### Everything here is provisional on the way the pages are designed, and what images they contain; what follows is for example purposes only!
// ##### For really simple pages containing just a single image that's always the one being refreshed, this function could be as simple as just the one line:
// ##### document.getElementById("myImage").src = "/img/1x1blank.gif";
var blankList = [],
fullSrc = /* Fully qualified (absolute) src - i.e. prepend protocol, server/domain, and path if not present in src */,
imgs, img, i;
for each (/* window accessible from this one, i.e. this window, and child frames/iframes, the parent window, anything opened via window.open(), and anything recursively reachable from there */)
{
// get list of matching images:
imgs = theWindow.document.body.getElementsByTagName("img");
for (i = imgs.length; i--;) if ((img = imgs[i]).src===fullSrc) // could instead use body.querySelectorAll(), to check both tag name and src attribute, which would probably be more efficient, where supported
{
img.src = "/img/1x1blank.gif"; // blank them
blankList.push(img); // optionally, save list of blanked images to make restoring easy later on
}
}
for each (/* img DOM node held only by javascript, for example in any image-caching script */) if (img.src===fullSrc)
{
img.src = "/img/1x1blank.gif"; // do the same as for on-page images!
blankList.push(img);
}
// ##### If necessary, do something here that tells all accessible windows not to create any *new* images with src===fullSrc, until further notice,
// ##### (or perhaps to create them initially blank instead and add them to blankList).
// ##### For example, you might have (say) a global object window.top.blankedSrces as a propery of your topmost window, initially set = {}. Then you could do:
// #####
// ##### var bs = window.top.blankedSrces;
// ##### if (bs.hasOwnProperty(src)) bs[src]++; else bs[src] = 1;
// #####
// ##### And before creating a new image using javascript, you'd first ensure that (blankedSrces.hasOwnProperty(src)) was false...
// ##### Note that incrementing a counter here rather than just setting a flag allows for the possibility that multiple forced-reloads of the same image are underway at once, or are overlapping.
return blankList; // optional - only if using blankList for restoring back the blanked images! This just gets passed in to imgReloadRestore(), it isn't used otherwise.
}
// This function restores all blanked images, that were blanked out by imgReloadBlank(src) for the matching src argument.
// ##### You should code the actual contents of this function according to your page design, and what images there are on them, as well as how/if images are dimensioned, etc!!! #####
function imgReloadRestore(src,blankList,imgDim,loadError);
{
// ##### Everything here is provisional on the way the pages are designed, and what images they contain; what follows is for example purposes only!
// ##### For really simple pages containing just a single image that's always the one being refreshed, this function could be as simple as just the one line:
// ##### document.getElementById("myImage").src = src;
// ##### if in imgReloadBlank() you did something to tell all accessible windows not to create any *new* images with src===fullSrc until further notice, retract that setting now!
// ##### For example, if you used the global object window.top.blankedSrces as described there, then you could do:
// #####
// ##### var bs = window.top.blankedSrces;
// ##### if (bs.hasOwnProperty(src)&&--bs[src]) return; else delete bs[src]; // return here means don't restore until ALL forced reloads complete.
var i, img, width = imgDim&&imgDim[0], height = imgDim&&imgDim[1];
if (width) width += "px";
if (height) height += "px";
if (loadError) {/* If you want, do something about an image that couldn't load, e.g: src = "/img/brokenImg.jpg"; or alert("Couldn't refresh image from server!"); */}
// If you saved & returned blankList in imgReloadBlank(), you can just use this to restore:
for (i = blankList.length; i--;)
{
(img = blankList[i]).src = src;
if (width) img.style.width = width;
if (height) img.style.height = height;
}
}
// Force an image to be reloaded from the server, bypassing/refreshing the cache.
// due to limitations of the browser API, this actually requires TWO load attempts - an initial load into a hidden iframe, and then a call to iframe.contentWindow.location.reload(true);
// If image is from a different domain (i.e. cross-domain restrictions are in effect, you must set isCrossDomain = true, or the script will crash!
// imgDim is a 2-element array containing the image x and y dimensions, or it may be omitted or null; it can be used to set a new image size at the same time the image is updated, if applicable.
// if "twostage" is true, the first load will occur immediately, and the return value will be a function
// that takes a boolean parameter (true to proceed with the 2nd load (including the blank-and-reload procedure), false to cancel) and an optional updated imgDim.
// This allows you to do the first load early... for example during an upload (to the server) of the image you want to (then) refresh.
function forceImgReload(src, isCrossDomain, imgDim, twostage)
{
var blankList, step = 0, // step: 0 - started initial load, 1 - wait before proceeding (twostage mode only), 2 - started forced reload, 3 - cancelled
iframe = window.document.createElement("iframe"), // Hidden iframe, in which to perform the load+reload.
loadCallback = function(e) // Callback function, called after iframe load+reload completes (or fails).
{ // Will be called TWICE unless twostage-mode process is cancelled. (Once after load, once after reload).
if (!step) // initial load just completed. Note that it doesn't actually matter if this load succeeded or not!
{
if (twostage) step = 1; // wait for twostage-mode proceed or cancel; don't do anything else just yet
else { step = 2; blankList = imgReloadBlank(src); iframe.contentWindow.location.reload(true); } // initiate forced-reload
}
else if (step===2) // forced re-load is done
{
imgReloadRestore(src,blankList,imgDim,(e||window.event).type==="error"); // last parameter checks whether loadCallback was called from the "load" or the "error" event.
if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
}
}
iframe.style.display = "none";
window.parent.document.body.appendChild(iframe); // NOTE: if this is done AFTER setting src, Firefox MAY fail to fire the load event!
iframe.addEventListener("load",loadCallback,false);
iframe.addEventListener("error",loadCallback,false);
iframe.src = (isCrossDomain ? "/echoimg.php?src="+encodeURIComponent(src) : src); // If src is cross-domain, script will crash unless we embed the image in a same-domain html page (using server-side script)!!!
return (twostage
? function(proceed,dim)
{
if (!twostage) return;
twostage = false;
if (proceed)
{
imgDim = (dim||imgDim); // overwrite imgDim passed in to forceImgReload() - just in case you know the correct img dimensions now, but didn't when forceImgReload() was called.
if (step===1) { step = 2; blankList = imgReloadBlank(src); iframe.contentWindow.location.reload(true); }
}
else
{
step = 3;
if (iframe.contentWindow.stop) iframe.contentWindow.stop();
if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
}
}
: null);
}
Ensuite, pour forcer une actualisation d'une image située sur le même domaine que votre page, vous pouvez simplement faire:
forceImgReload("myimage.jpg");
Pour actualiser une image d'un autre endroit (cross-domain):
forceImgReload("http://someother.server.com/someimage.jpg", true);
Une application plus avancée pourrait être de recharger une image après avoir téléchargé une nouvelle version serveur, la préparation de l'étape initiale du processus de rechargement simultanée avec le téléchargement, pour minimiser le retard de rechargement visible à l'utilisateur. Si vous effectuez le téléchargement via AJAX, et que le serveur retourne un tableau JSON très simple [success, width, height] alors votre code pourrait ressembler à ceci:
// fileForm is a reference to the form that has a the <input typ="file"> on it, for uploading.
// serverURL is the url at which the uploaded image will be accessible from, once uploaded.
// The response from uploadImageToServer.php is a JSON array [success, width, height]. (A boolean and two ints).
function uploadAndRefreshCache(fileForm, serverURL)
{
var xhr = new XMLHttpRequest(),
proceedWithImageRefresh = forceImgReload(serverURL, false, null, true);
xhr.addEventListener("load", function(){ var arr = JSON.parse(xhr.responseText); if (!(arr&&arr[0])) { proceedWithImageRefresh(false); doSomethingOnUploadFailure(...); } else { proceedWithImageRefresh(true,[arr[1],ar[2]]); doSomethingOnUploadSuccess(...); }});
xhr.addEventListener("error", function(){ proceedWithImageRefresh(false); doSomethingOnUploadError(...); });
xhr.addEventListener("abort", function(){ proceedWithImageRefresh(false); doSomethingOnUploadAborted(...); });
// add additional event listener(s) to track upload progress for graphical progress bar, etc...
xhr.open("post","uploadImageToServer.php");
xhr.send(new FormData(fileForm));
}
Une note finale: bien que ce sujet concerne les images, il s'applique potentiellement à d'autres types de fichiers ou de ressources. Par exemple, empêcher l'utilisation de script périmé ou fichiers CSS, ou peut-être même rafraîchir les documents PDF mis à jour (en utilisant (4) seulement si configuré pour ouvrir dans le navigateur). La méthode (4) peut nécessiter quelques modifications du javascript ci-dessus, dans ces cas.
Comme alternative à...
newImage.src = "http://localhost/image.jpg?" + new Date().getTime();
...Il semble que...
newImage.src = "http://localhost/image.jpg#" + new Date().getTime();
... est suffisant pour tromper le cache du navigateur sans contourner les caches en amont, en supposant que vous avez renvoyé les en-têtes Cache-Control
corrects. Bien que vous pouvez utiliser...
Cache-Control: no-cache, must-revalidate
...vous perdez les avantages des en-têtes If-Modified-Since
ou If-None-Match
, donc quelque chose comme...
Cache-Control: max-age=0, must-revalidate
...devrait empêcher le navigateur de re-télécharger l'image entière si elle n'a pas réellement changé. Testé et travaillant sur IE, Firefox, et Chrome. Fâcheusement, il échoue sur Safari sauf si vous utilisez...
Cache-Control: no-store
...bien que cela puisse être préférable au remplissage des caches en amont avec des centaines d'images identiques, en particulier lorsqu'elles s'exécutent sur votre propre serveur. ;-)
Update (2014-09-28): de nos jours, il semble que Cache-Control: no-store
soit également nécessaire pour Chrome.
Après avoir créé la nouvelle image, supprimez-vous l'Ancienne image du DOM et remplacez-la par la nouvelle?
Vous pourriez saisir de nouvelles images chaque appel updateImage, mais ne pas les ajouter à la page.
Il y a un certain nombre de façons de le faire. Quelque chose comme ça fonctionnerait.
function updateImage()
{
var image = document.getElementById("theText");
if(image.complete) {
var new_image = new Image();
//set up the new image
new_image.id = "theText";
new_image.src = image.src;
// insert new image and remove old
image.parentNode.insertBefore(new_image,image);
image.parentNode.removeChild(image);
}
setTimeout(updateImage, 1000);
}
Après avoir fonctionné, s'il y a encore des problèmes, c'est probablement un problème de mise en cache comme les autres réponses parlent.
Une réponse est d'ajouter hackishly un paramètre de requête get comme cela a été suggéré.
Une meilleure réponse est d'émettre quelques options supplémentaires dans votre en-tête HTTP.
Pragma: no-cache
Expires: Fri, 30 Oct 1998 14:19:41 GMT
Cache-Control: no-cache, must-revalidate
En fournissant une date dans le passé, il ne sera pas mis en cache par le navigateur. Cache-Control
a été ajouté dans HTTP / 1.1 et la balise must-revalidate indique que les proxies ne devraient jamais servir une ancienne image même dans des circonstances atténuantes, et le Pragma: no-cache
n'est pas vraiment nécessaire pour les navigateurs/caches modernes actuels mais peut aider avec quelques vieilles implémentations cassées crufty.
function reloadImage(imageId)
{
path = '../showImage.php?cache='; //for example
imageObject = document.getElementById(imageId);
imageObject.src = path + (new Date()).getTime();
}
<img src='../showImage.php' id='myimage' />
<br/>
<input type='button' onclick="reloadImage('myimage')" />
Ce que j'ai fini par faire, c'est que le serveur mappe toute demande d'image dans ce répertoire à la source que j'essayais de mettre à jour. J'ai ensuite demandé à mon minuteur d'ajouter un numéro à la fin du nom afin que le DOM le voie comme une nouvelle image et le charge.
Par exemple
http://localhost/image.jpg
//and
http://localhost/image01.jpg
Demandera le même code de génération d'image mais il ressemblera à des images différentes pour le navigateur.
var newImage = new Image();
newImage.src = "http://localhost/image.jpg";
var count = 0;
function updateImage()
{
if(newImage.complete) {
document.getElementById("theText").src = newImage.src;
newImage = new Image();
newImage.src = "http://localhost/image/id/image" + count++ + ".jpg";
}
setTimeout(updateImage, 1000);
}
Essayez d'utiliser une chaîne de requête sans valeur pour en faire une url unique:
function updateImage()
{
if(newImage.complete) {
document.getElementById("theText").src = newImage.src;
newImage = new Image();
number++;
newImage.src = "http://localhost/image.jpg?" + new Date();
}
setTimeout(updateImage, 1000);
}
document.getElementById("img-id").src = document.getElementById("img-id").src
Définit son propre src comme src.
J'avais une exigence: 1) ne peut pas ajouter de ?var=xx
à l'image 2) cela devrait fonctionner cross-domain
, j'aime beaucoup le n ° 4 option cette réponse, avec un mais:
- il a des problèmes à travailler avec crossdomain de manière fiable (et il nécessite de toucher le code du serveur).
Ma façon rapide et sale est:
- créer un iframe caché
- chargez la page actuelle (Oui l'ensemble page)
iframe.contentWindow.location.reload(true);
- réinitialiser la source de l'image sur elle-même
Voilà
function RefreshCachedImage() {
if (window.self !== window.top) return; //prevent recursion
var $img = $("#MYIMAGE");
var src = $img.attr("src");
var iframe = document.createElement("iframe");
iframe.style.display = "none";
window.parent.document.body.appendChild(iframe);
iframe.src = window.location.href;
setTimeout(function () {
iframe.contentWindow.location.reload(true);
setTimeout(function () {
$img.removeAttr("src").attr("src", src);
}, 2000);
}, 2000);
}
Ouais, je sais, setTimeout... Vous devez changer cela pour les événements onload appropriés.
J'ai résolu ce problème en renvoyant les données via un servlet.
response.setContentType("image/png");
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache, must-revalidate");
response.setDateHeader("Expires", 0);
BufferedImage img = ImageIO.read(new File(imageFileName));
ImageIO.write(img, "png", response.getOutputStream());
Ensuite, à partir de la page, vous lui donnez simplement la servlet avec quelques paramètres pour récupérer le fichier image correct.
<img src="YourServlet?imageFileName=imageNum1">
Voici ma solution. C'est très simple. La planification des images pourrait être meilleure.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Image Refresh</title>
</head>
<body>
<!-- Get the initial image. -->
<img id="frame" src="frame.jpg">
<script>
// Use an off-screen image to load the next frame.
var img = new Image();
// When it is loaded...
img.addEventListener("load", function() {
// Set the on-screen image to the same source. This should be instant because
// it is already loaded.
document.getElementById("frame").src = img.src;
// Schedule loading the next frame.
setTimeout(function() {
img.src = "frame.jpg?" + (new Date).getTime();
}, 1000/15); // 15 FPS (more or less)
})
// Start the loading process.
img.src = "frame.jpg?" + (new Date).getTime();
</script>
</body>
</html>
Fortement basé sur le code #4 de Doin, l'exemple ci-dessous simplifie ce code en utilisant document.write
au lieu de src
dans le iframe
pour supporter CORS. Se concentre également uniquement sur la suppression du cache du navigateur, ne rechargeant pas toutes les images de la page.
Ci-dessous est écrit en typescript
et utilise le angular
$q bibliothèque de promesses, juste pour info, mais devrait être assez facile à porter à Vanille javascript. La méthode est destinée à vivre dans une classe typescript.
Renvoie une promesse qui sera résolue lorsque l'iframe a terminé le rechargement. Pas fortement testé, mais fonctionne bien pour nous.
mmForceImgReload(src: string): ng.IPromise<void> {
var deferred = $q.defer<void>();
var iframe = window.document.createElement("iframe");
var firstLoad = true;
var loadCallback = (e) => {
if (firstLoad) {
firstLoad = false;
iframe.contentWindow.location.reload(true);
} else {
if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
deferred.resolve();
}
}
iframe.style.display = "none";
window.parent.document.body.appendChild(iframe);
iframe.addEventListener("load", loadCallback, false);
iframe.addEventListener("error", loadCallback, false);
var doc = iframe.contentWindow.document;
doc.open();
doc.write('<html><head><title></title></head><body><img src="' + src + '"></body></html>');
doc.close();
return deferred.promise;
}
J'ai utilisé le concept ci-dessous de lier d'abord l'image avec une url fausse(tampon) et de la lier ensuite avec l'url valide.
imgcover.ImageUrl = ConfigurationManager.AppSettings["profileLargeImgPath"] + "Myapp_CoverPic_" + userid + "Buffer.jpg";
imgcover.ImageUrl = ConfigurationManager.AppSettings["profileLargeImgPath"] + "Myapp_CoverPic_" + userid + ".jpg";
De cette façon, je force le navigateur à actualiser avec une url valide.
<img src='someurl.com/someimage.ext' onload='imageRefresh(this, 1000);'>
Puis ci-dessous dans certains javascript
<script language='javascript'>
function imageRefresh(img, timeout) {
setTimeout(function() {
var d = new Date;
var http = img.src;
if (http.indexOf("&d=") != -1) { http = http.split("&d=")[0]; }
img.src = http + '&d=' + d.getTime();
}, timeout);
}
</script>
Et donc ce que cela fait, c'est, lorsque l'image se charge, la planifie pour être rechargée en 1 seconde. Je l'utilise sur une page avec des caméras de sécurité à domicile de type variable.
Le code suivant est utile pour actualiser l'image lorsqu'un bouton est cliqué.
function reloadImage(imageId) {
imgName = 'vishnu.jpg'; //for example
imageObject = document.getElementById(imageId);
imageObject.src = imgName;
}
<img src='vishnu.jpg' id='myimage' />
<input type='button' onclick="reloadImage('myimage')" />