javascript - property - Actualizar la imagen con una nueva en la misma url
title label html (16)
Estoy accediendo a un enlace en mi sitio que proporcionará una nueva imagen cada vez que se acceda.
El problema que tengo es que si intento cargar la imagen en segundo plano y luego actualizar la de la página, la imagen no cambia, aunque se actualiza cuando recargo la página.
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);
}
Encabezados como FireFox los ve:
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
Necesito forzar una actualización de solo esa imagen en la página. ¿Algunas ideas?
Aquí está mi solución. Es muy sencillo. La programación de cuadros podría ser mejor.
<!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>
Como alternativa a ...
newImage.src = "http://localhost/image.jpg?" + new Date().getTime();
...parece que...
newImage.src = "http://localhost/image.jpg#" + new Date().getTime();
... es suficiente para engañar al caché del navegador sin pasar por alto ningún caché ascendente, asumiendo que devolvió los encabezados de Cache-Control
correctos. Aunque puedes usar ...
Cache-Control: no-cache, must-revalidate
... pierde los beneficios de los encabezados If-Modified-Since
o If-None-Match
, así que algo como ...
Cache-Control: max-age=0, must-revalidate
... debería evitar que el navegador vuelva a descargar la imagen completa si no ha cambiado realmente. Probado y trabajando en IE, Firefox y Chrome. Molesto, falla en Safari a menos que uses ...
Cache-Control: no-store
... aunque esto puede ser preferible a llenar cachés ascendentes con cientos de imágenes idénticas, especialmente cuando se ejecutan en su propio servidor. ;-)
Actualización (2014-09-28): Hoy en día parece que Cache-Control: no-store
se necesita Cache-Control: no-store
para Chrome también.
Después de crear la nueva imagen, ¿está eliminando la imagen antigua del DOM y reemplazándola con la nueva?
Podría estar capturando nuevas imágenes en cada llamada de updateImage, pero sin agregarlas a la página.
Hay varias formas de hacerlo. Algo como esto funcionaría.
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);
}
Después de hacer que funcione, si todavía hay problemas, es probable que se trate de un problema de almacenamiento en caché al que se refieren las otras respuestas.
He visto muchas variaciones en las respuestas sobre cómo hacer esto, así que pensé en resumirlas aquí (además de agregar un cuarto método de mi propio invento):
(1) Agregue un único parámetro de consulta de almacenamiento en memoria caché a la URL, como por ejemplo:
newImage.src = "image.jpg?t=" + new Date().getTime();
Pros: 100% confiable, rápido y fácil de entender e implementar.
Contras: Omite el almacenamiento en caché por completo, lo que significa retrasos innecesarios y uso de ancho de banda siempre que la imagen no cambie entre las vistas. ¡Potencialmente llenará el caché del navegador (y cualquier caché intermedio) con muchas, muchas copias de exactamente la misma imagen! Además, requiere modificar la URL de la imagen.
Cuándo usarlo: use cuando la imagen cambia constantemente, por ejemplo, para una transmisión de webcam en vivo. Si usas este método, asegúrate de servir las imágenes con Cache-control: no-cache
¡encabezados HTTP Cache-control: no-cache
! (A menudo, esto se puede configurar utilizando un archivo .htaccess). De lo contrario, irás llenando las cachés progresivamente con versiones antiguas de la imagen.
(2) Agregue el parámetro de consulta a la URL que cambia solo cuando lo hace el archivo, por ejemplo:
echo ''<img src="image.jpg?m='' . filemtime(''image.jpg'') . ''">'';
(Ese es el código del lado del servidor PHP, pero el punto importante aquí es simplemente que una cadena de consulta? M = [hora de la última modificación del archivo] se adjunta al nombre del archivo).
Pros: 100% confiable, rápido y fácil de entender e implementar, y conserva perfectamente las ventajas del almacenamiento en caché.
Contras: Requiere modificar la URL de la imagen. Además, un poco más de trabajo para el servidor: tiene que obtener acceso al archivo modificado por última vez. Además, requiere información del lado del servidor, por lo que no es adecuado para una solución puramente del lado del cliente para buscar una imagen actualizada.
Cuándo usarlo: cuando desee almacenar imágenes en caché, pero es posible que deba actualizarlas al final del servidor de vez en cuando sin cambiar el nombre del archivo. Y cuando puede asegurarse fácilmente de que se agrega la cadena de consulta correcta a cada instancia de imagen en su HTML.
(3) Sirva sus imágenes con el encabezado Cache-control: max-age=0, must-revalidate
, y agregue un identificador de fragmento único de memcache -busting a la URL, como por ejemplo:
newImage.src = "image.jpg#" + new Date().getTime();
La idea aquí es que el encabezado de control de caché coloca imágenes en el caché del navegador, pero las marca inmediatamente como obsoletas, de modo que, cada vez que se vuelven a mostrar, el navegador debe verificar con el servidor para ver si han cambiado. Esto asegura que la memoria caché HTTP del navegador siempre devuelva la última copia de la imagen. Sin embargo, los navegadores a menudo reutilizan una copia en memoria de una imagen si la tienen, y ni siquiera comprueban su caché HTTP en ese caso. Para evitar esto, se utiliza un identificador de fragmento: la comparación de la imagen en memoria src
incluye el identificador de fragmento, pero se elimina antes de consultar la memoria caché HTTP. (Así, por ejemplo, image.jpg#A
y image.jpg#B
pueden mostrarse desde la entrada image.jpg
en el caché HTTP del navegador, pero image.jpg#B
nunca se mostraría usando datos de imagen retenidos en la memoria de cuando image.jpg#A
se mostró por última vez).
Ventajas: hace un uso adecuado de los mecanismos de almacenamiento en caché de HTTP y utiliza imágenes en caché si no han cambiado. Funciona para servidores que se atragantan con una cadena de consulta agregada a una URL de imagen estática (ya que los servidores nunca ven los identificadores de fragmentos, son para uso exclusivo de los navegadores).
Contras: se basa en un comportamiento algo dudoso (o al menos mal documentado) de los navegadores, con respecto a las imágenes con identificadores de fragmentos en sus URL (sin embargo, he probado esto con éxito en FF27, Chrome33 e IE11). Sigue enviando una solicitud de revalidación al servidor para cada vista de imagen, lo que puede ser excesivo si las imágenes cambian rara vez y / o la latencia es un gran problema (ya que debe esperar la respuesta de revalidación incluso cuando la imagen almacenada en caché aún es buena) . Requiere modificar las URL de las imágenes.
Cuándo usar: use cuándo las imágenes pueden cambiar con frecuencia, o el cliente debe actualizarlas de forma intermitente sin la participación de scripts del lado del servidor, pero donde aún desea la ventaja del almacenamiento en caché. Por ejemplo, sondeando una cámara web en vivo que actualiza una imagen de forma irregular cada pocos minutos. Alternativamente, use en lugar de (1) o (2) si su servidor no permite cadenas de consulta en las URL de imágenes estáticas.
(4) Actualice por la fuerza una imagen en particular usando Javascript, primero cargándola en un <iframe>
oculto y luego llamando a location.reload(true)
en el contentWindow
del iframe.
Los pasos son:
Cargue la imagen a actualizar en un iframe oculto. Este es solo un paso de configuración: se puede hacer con mucha anticipación la actualización real, si se desea. ¡Ni siquiera importa si la imagen no se carga en esta etapa!
Una vez hecho esto, elimine todas las copias de esa imagen en su (s) página (s) o en cualquier lugar en cualquier nodo DOM (incluso fuera de la página almacenados en variables javascript). Esto es necesario porque, de lo contrario, el navegador puede mostrar la imagen de una copia en memoria obsoleta (IE11 lo hace especialmente): debe asegurarse de que todas las copias en memoria estén borradas, antes de actualizar la memoria caché HTTP. Si otro código javascript se ejecuta de forma asíncrona, es posible que también deba evitar que ese código cree nuevas copias de la imagen que se actualizará mientras tanto.
Llame a
iframe.contentWindow.location.reload(true)
. Eltrue
fuerza una omisión de caché, recargando directamente desde el servidor y sobrescribiendo la copia en caché existente.Una vez que haya terminado de volver a cargar, restaure las imágenes en blanco. ¡Ahora deberían mostrar la versión nueva del servidor!
Para imágenes del mismo dominio, puede cargar la imagen directamente en el iframe. Para las imágenes de varios dominios, debe cargar una página HTML de su dominio que contenga la imagen en una etiqueta <img>
, de lo contrario obtendrá un error de "Acceso denegado" al intentar llamar a iframe.contentWindow.reload(...)
.
Pros: Funciona igual que la función image.reload () que desearías que tuviera el DOM! Permite que las imágenes se almacenen en caché normalmente (incluso con fechas de vencimiento futuras si las desea, evitando así la revalidación frecuente). Le permite actualizar una imagen en particular sin alterar las URL de esa imagen en la página actual, o en cualquier otra página, usando solo el código del lado del cliente.
Contras: Se basa en Javascript. No se garantiza al 100% que funcione correctamente en todos los navegadores (aunque he probado esto con éxito en FF27, Chrome33 e IE11). Muy complicado en relación a los otros métodos.
Cuándo usarlo: cuando tiene una colección de imágenes básicamente estáticas que le gustaría almacenar en caché, pero todavía necesita poder actualizarlas de vez en cuando y obtener retroalimentación visual inmediata de la actualización. (Especialmente cuando solo actualizar la página del navegador no funcionaría, como en algunas aplicaciones web basadas en AJAX, por ejemplo). Y cuando los métodos (1) - (3) no son factibles porque (por cualquier razón) no puede cambiar todas las URL que podrían mostrar la imagen que necesita actualizar. (Tenga en cuenta que al usar esos 3 métodos, la imagen se actualizará, pero si otra página intenta mostrar esa imagen sin la cadena de consulta o el identificador de fragmento apropiado, puede mostrar una versión anterior).
Los detalles para implementar esto de una manera robusta y flexible de hadas se dan a continuación:
Supongamos que su sitio web contiene un .gif de 1x1 píxeles en la ruta URL /img/1x1blank.gif
, y también tiene el siguiente script PHP de una línea (solo necesario para aplicar la actualización forzada a imágenes de dominios cruzados) y se puede volver a escribir en cualquier lenguaje de script del lado del servidor, por supuesto) en la ruta URL /echoimg.php
:
<img src="<?=htmlspecialchars(@$_GET[''src''],ENT_COMPAT|ENT_HTML5,''UTF-8'')?>">
Entonces, aquí hay una implementación realista de cómo podrías hacer todo esto en Javascript. Parece un poco complicado, pero hay muchos comentarios, y la función importante es solo forceImgReload (), las dos primeras imágenes en blanco y en blanco, y deben diseñarse para que funcionen de manera eficiente con su propio HTML, así que codifíquelas. funciona mejor para usted; muchas de las complicaciones en ellas pueden ser innecesarias para su sitio 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);
}
Luego, para forzar una actualización de una imagen ubicada en el mismo dominio que tu página, puedes simplemente hacer:
forceImgReload("myimage.jpg");
Para actualizar una imagen desde otro lugar (dominio cruzado):
forceImgReload("http://someother.server.com/someimage.jpg", true);
Una aplicación más avanzada podría ser recargar una imagen después de cargar una nueva versión en su servidor, preparando la etapa inicial del proceso de recarga simultáneamente con la carga, para minimizar el retraso de recarga visible para el usuario. Si está realizando la carga a través de AJAX, y el servidor está devolviendo una matriz JSON muy simple [éxito, ancho, alto], entonces su código podría tener este aspecto:
// 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));
}
Una nota final: aunque este tema trata sobre imágenes, también se aplica a otros tipos de archivos o recursos. Por ejemplo, evitar el uso de scripts obsoletos o archivos css, o tal vez incluso actualizar documentos PDF actualizados (usando (4) solo si está configurado para abrirse en el navegador). El método (4) puede requerir algunos cambios en el javascript anterior, en estos casos.
Intente agregar un cachebreaker al final de la url:
newImage.src = "http://localhost/image.jpg?" + new Date().getTime();
Esto agregará automáticamente la marca de tiempo actual cuando esté creando la imagen, y hará que el navegador busque nuevamente la imagen en lugar de recuperar la que está en el caché.
Intente usar una cadena de consulta sin valor para convertirla en una URL única:
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);
}
Lo que terminé haciendo fue que el servidor asignara cualquier solicitud de una imagen en ese directorio a la fuente que estaba intentando actualizar. Luego, mi temporizador agregó un número al final del nombre para que el DOM lo viera como una nueva imagen y lo cargara.
P.ej
http://localhost/image.jpg
//and
http://localhost/image01.jpg
solicitará el mismo código de generación de imágenes, pero se verá como imágenes diferentes al navegador.
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);
}
Resolví este problema enviando los datos a través de 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());
Luego, desde la página, solo le das el servlet con algunos parámetros para obtener el archivo de imagen correcto.
<img src="YourServlet?imageFileName=imageNum1">
Tenía un requisito: 1) no puedo agregar ?var=xx
a la imagen 2) debería funcionar en varios dominios
Realmente me gusta la opción # 4 en esta respuesta con una, pero:
- tiene problemas para trabajar con crossdomain de manera confiable (y requiere tocar el código del servidor).
Mi forma rápida y sucia es:
- Crear iframe oculto
- Cargue la página actual (sí, toda la página)
-
iframe.contentWindow.location.reload(true);
- Reajuste la fuente de la imagen a sí mismo
Aquí está
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);
}
Sí, lo sé, setTimeout ... Tienes que cambiarlo a los eventos de carga adecuados.
Una respuesta es agregar piraticamente algunos parámetros de consulta como se ha sugerido.
Una mejor respuesta es emitir un par de opciones adicionales en su encabezado HTTP.
Pragma: no-cache
Expires: Fri, 30 Oct 1998 14:19:41 GMT
Cache-Control: no-cache, must-revalidate
Al proporcionar una fecha en el pasado, el navegador no la almacenará en caché. Cache-Control
se agregó en HTTP / 1.1 y la etiqueta must-revalidate indica que los proxies nunca deben mostrar una imagen antigua, incluso en circunstancias atenuantes, y Pragma: no-cache
no es realmente necesario para los navegadores / cachés actuales. Ayuda con algunas implementaciones viejas y rotas.
El siguiente código es útil para actualizar la imagen cuando se hace clic en un botón.
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'')" />
Utilicé el siguiente concepto de primero vincular la imagen con una url falsa (buffer) y luego vincularla con la url válida.
imgcover.ImageUrl = ConfigurationManager.AppSettings["profileLargeImgPath"] + "Myapp_CoverPic_" + userid + "Buffer.jpg";
imgcover.ImageUrl = ConfigurationManager.AppSettings["profileLargeImgPath"] + "Myapp_CoverPic_" + userid + ".jpg";
De esta manera, estoy obligando a que el navegador se actualice con una URL válida.
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'')" />
Basándose en gran medida en el código # 4 de Doin, el siguiente ejemplo simplifica ese código en gran medida utilizando en document.write
lugar de src
en el iframe
CORS de soporte. También se enfoca solo en destruir la memoria caché del navegador, no en recargar todas las imágenes de la página.
A continuación, está escrito typescript
y utiliza la biblioteca de promesas de angular
$q , solo para su información, pero debería ser lo suficientemente fácil de portar a javascript de vainilla. El método está destinado a vivir dentro de una clase de escritura.
Devuelve una promesa que se resolverá cuando el iframe haya completado la recarga. No muy probado, pero funciona bien para nosotros.
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;
}
<img src=''someurl.com/someimage.ext'' onload=''imageRefresh(this, 1000);''>
Entonces abajo en algunos 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>
Y lo que esto hace es que, cuando la imagen se carga, la programa para recargarla en 1 segundo. Estoy usando esto en una página con cámaras de seguridad domésticas de diferentes tipos.
document.getElementById("img-id").src = document.getElementById("img-id").src
establece su propio src como su src.