Pregunta sobre url, javascript, refresh, image – Actualiza la imagen con una nueva en la misma url

285

Estoy accediendo a un enlace en mi sitio que proporcionará una nueva imagen cada vez que se acceda.

El problema que estoy encontrando 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?

Tu respuesta

16   la respuesta
2
document.getElementById("img-id").src = document.getElementById("img-id").src

0

el siguiente ejemplo simplifica ese código en gran medida utilizandodocument.write en lugar desrcen eliframe para apoyar CORS. También se enfoca solo en destruir la memoria caché del navegador, no en recargar todas las imágenes de la página.

A continuacion esta escrito entypescript y usa elangular $ q biblioteca de promesas, solo para tu 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;
    }
0

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">
174

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ó el correctoCache-Control encabezados Aunque puedes usar ...

Cache-Control: no-cache, must-revalidate

... pierdes los beneficios de laIf-Modified-Since oIf-None-Match encabezados, 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. ;-)

Actualizar (2014-09-28): Hoy en día parece queCache-Control: no-store También es necesario para Chrome.

¡Genial! Después de mucho tiempo tratando de cargar mis imágenes web que estaban siendo cargadas con un retraso, simplemente lo resolví aplicando su solución (con '#', usar '?' No funciona para mí). ¡¡¡Muchas gracias!!! user304602
Para evitar la sobrecarga de la creación de objetos y / o la llamada de método, podría usar un entero incremental como el destructor de caché:newImage.src = "http://localhost/image.jpg#" + i++; laindir
Hay varios caché de encabezado. en realidad no sé muy bien el inglés, por favor, ¿puedes decirme si debo usar cuál? Quiero algo que no almacene en caché solo la foto que se ha cambiado (como un captcha), y que almacene en caché otras cosas. asi queCache-Control: max-age=0, must-revalidate ¿es bueno para mí? Shafizadeh
No funciona para mí. Lo único diferente en mi caso es que tengo una URL para una acción del controlador que recupera img de db. Tenía otros argumentos para la acción del controlador, así que lo agregué como "...... & convert = true & t =" + new Date (). GetTime (); y "...... & convert = true #" + new Date (). getTime () ;. ¿Hay algo que estoy haciendo mal? shaffooo
ExistenDOS cachés involucrados aquí: hay un caché HTTP regular del navegador, y un caché de imágenes en memoria que se ha mostrado recientemente. Este último caché en memoria está indexado por el completosrc atributo, por lo que agregar un identificador de fragmento único garantiza que la imagen no se extraiga simplemente de la memoria. Pero los identificadores de fragmentos no se envían como parte de las solicitudes HTTP, por lo que el caché HTTP normal se usará normalmente. Es por eso que esta técnica funciona. Doin
0
<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.

4

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, yPragma: no-cache no es realmente necesario para los navegadores / cachés modernos actuales, pero puede ayudar con algunas implementaciones antiguas e inestables.

Esto sonaba como si hubiera funcionado pero aún muestra la misma imagen, incluso con los hacks. Añadiré la información del encabezado a la pregunta. QueueHammer
Acabo de notar que estás actualizando la misma etiqueta img una y otra vez. El navegador probablemente está detectando cuando configura el src de que el src no ha cambiado, por lo que no se molesta en actualizar. (Dado que esta comprobación se realiza a nivel de DOM y no tiene nada que ver con el objetivo). ¿Qué pasa si añades "?" + número - a la url de la imagen que se está recuperando? Edward KMETT
6

¿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.

1

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);
}
Se agregó el WQS al código y se verificó que la solicitud está siendo aceptada y que el navegador considera que la respuesta proviene de la dirección + WQS sin la actualización de la imagen. QueueHammer
305

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é.

¿Está bien para ser usado en Amazon S3? Bruno Peres
Gracias @Paolo Bergantino por esta respuesta. Estoy perdiendo mis tres días para borrar la imagen de Chache Coder
Ahi estaDate.now() para esto vp_arth
o si necesita una función para usarla en varias imágenes, siempre puede seguir agregando &:newImage.src+='&' Neville Nazerane
2

ud 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);
}
Esto tendría el mismo problema de almacenar en caché múltiples copias de la imagen que la solución de la cadena de consulta (Paolo y algunas otras), y requiere cambios en el servidor. TomG
1

lic 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')" />
188

así que pensé en resumirlas aquí (además de agregar un cuarto método de mi propia invención):

(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 cuando la imagenno hace Cambio entre 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 usar: Se utiliza 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 ellos mismos.Cache-control: no-cache Encabezados HTTP !!! (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 a? M =[última hora modificada del archivo] la cadena de consulta se adjunta al nombre de 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 a la hora del último archivo modificado. Además, requiere información del lado del servidor, por lo que no es adecuado para una solución exclusivamente del lado del cliente para buscar una imagen actualizada.

Cuándo usar: 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) Sirve tus imágenes con el encabezado.Cache-control: max-age=0, must-revalidate, y añadir un únicomemcache-busting identificador de fragmento 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 las 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 consultar con el servidor para ver si han cambiado. Esto asegura que el navegadorCaché HTTP Siempre devuelve la última copia de la imagen. Sin embargo, los navegadores a menudo reutilizarán una copia en memoria de una imagen si la tienen, y ni siquiera verifican su caché HTTP en ese caso. Para evitar esto, se utiliza un identificador de fragmento: Comparación de la imagen en memoriasrcIncluye el identificador del fragmento, pero se elimina antes de consultar la memoria caché HTTP. (Así, por ejemplo,image.jpg#A yimage.jpg#B ambos podrían ser mostrados desde elimage.jpg entrada en el caché HTTP del navegador, peroimage.jpg#B nunca se mostraría usando datos de imagen retenidos en la memoria de cuandoimage.jpg#A se mostró por última vez).

Pros: Hace un uso adecuado de los mecanismos de almacenamiento en caché 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 un tanto 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: Utilícela cuando 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 a la fuerza una imagen en particular usando Javascript, primero cargándola en un oculto<iframe> y luego llamandolocation.reload(true) en el iframecontentWindow.

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 especialmente lo hace): debe asegurarse de que todosen memoria Las copias se borran, antes de actualizar la memoria caché HTTP. Si se ejecuta otro código javascript 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.

Llamadaiframe.contentWindow.location.reload(true). lostrue fuerza una omisión de caché, se recarga directamente desde el servidor y sobrescribe la copia en caché existente.

Una vez terminadore-cargar, restaurar 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 dominios cruzados, debe cargar una página HTMLde tu dominio que contiene la imagen en una<img> etiqueta, de lo contrario obtendrá un error de "Acceso denegado" cuando intente llamariframe.contentWindow.reload(...).

Pros: Funciona igual que la función image.reload () quedeseo ¡El DOM tenía! 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 usar: 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 ocasionalmente y obtener una respuesta 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 utilizando esos 3 métodos, la imagen se actualizará, pero siotro La página intenta mostrar esa imagensin la cadena de consulta apropiada o el identificador de fragmento, puede mostrar una versión anterior en su lugar).

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 de la URL/img/1x1blank.gif, y también tiene el siguiente script PHP de una línea (solo necesario para aplicar la actualización forzada adominio cruzado imágenes, y se pueden reescribir 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 solo en blanco y no 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.

@ADTC r.e. El comportamiento de Chrome ... Hmm, realmente no debería estar haciendo eso. ¿Está seguro de que los encabezados de control de caché enviados con el archivo de imagen (cuando se incluye una cadena de consulta) están configurados para permitir el almacenamiento en caché? Puedes verificarlos usando la pestaña de red de herramientas F12. Doin
@Doin para el método 2, ¿no es mejor si lo hacemos?clearstatcache(true, 'image.jpg'); ¿primero? Leí que PHP almacenará en caché las estadísticas del archivo, y entiendo que incluso si se cambia el mtime real, PHP todavía puede generar el mtime anterior.Jugo. ADTC
@Doin también, para el método 2, estaba probando en Chrome, y parece que cuando agrega el?m= parte, el navegador pasa por alto la memoria caché y golpea el servidor cada vez. No se si# Resolverá esto o introducirá su propio conjunto de problemas. ADTC
@ADTC Estoy bastante seguro de que PHP solo almacena estadísticas de archivosdentro de un guión individual, es decir, si el código de su script lee alguna información de archivo y luego la vuelve a leer, la segunda copia será desde el statcache. Para el propósito descrito aquí, probablemente sea el comportamiento correcto: si tiene dos o más copias de la misma imagen en su página HTML, todas deben tener la misma URL, incluso si la imagen se actualiza a mitad del script PHP que genera la página. Doin
3

{
   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')" />

cambiopath='../showImage.php'; apath='../showImage.php?'; BOOMik
explique al OP cómo y por qué esto ayuda en lugar de simplemente pegar el código nomistic
No creo que../showImage.phpFri May 01 2015 17:34:18 GMT+0200 (Mitteleuropäische Sommerzeit) es un nombre de archivo válido ... Al menos esto es lo que intenta cargar ... ByteHamster
1

?var=xx a la imagen 2) debe funcionar de dominio cruzado

Realmente me gusta la opción # 4 enesta respuesta con uno 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 ocultoCarga la página actual en ella. (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.

0

rí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>
-2

l 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.

Preguntas relacionadas