javascript - with - title html css




Atualizar a imagem com uma nova no mesmo URL (11)

Como uma alternativa para ...

newImage.src = "http://localhost/image.jpg?" + new Date().getTime();

...parece que...

newImage.src = "http://localhost/image.jpg#" + new Date().getTime();

... é suficiente para enganar o cache do navegador sem ignorar quaisquer caches upstream, supondo que você retornou os cabeçalhos Cache-Control corretos. Embora você possa usar ...

Cache-Control: no-cache, must-revalidate

... você perde os benefícios dos cabeçalhos If-Modified-Since ou If-None-Match , então algo como ...

Cache-Control: max-age=0, must-revalidate

... deve impedir que o navegador baixe novamente a imagem inteira se ela não tiver sido realmente alterada. Testado e trabalhando no IE, Firefox e Chrome. Irritantemente, ele falha no Safari, a menos que você use ...

Cache-Control: no-store

... embora isso ainda seja preferível ao preenchimento de caches upstream com centenas de imagens idênticas, particularmente quando elas estão sendo executadas em seu próprio servidor. ;-)

Atualização (2014-09-28): Hoje em dia, parece que o Cache-Control: no-store é necessário para o Chrome.

Estou acessando um link no meu site que fornecerá uma nova imagem toda vez que for acessada.

O problema que estou enfrentando é que, se eu tentar carregar a imagem em segundo plano e depois atualizar a imagem na página, a imagem não será alterada - embora seja atualizada quando eu recarregar a 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);
}

Cabeçalhos como o FireFox os vê:

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

Eu preciso forçar uma atualização apenas dessa imagem na página. Alguma ideia?


Depois de criar a nova imagem, você está removendo a imagem antiga do DOM e a substituindo pela nova?

Você poderia estar pegando novas imagens a cada chamada updateImage, mas não adicionando-as à página.

Existem várias maneiras de fazer isso. Algo assim funcionaria.

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);
}

Depois de obter esse trabalho, se ainda houver problemas, provavelmente é um problema de cache como as outras respostas falam.


Eu resolvi esse problema enviando os dados de volta por meio de um 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());

Então, a partir da página, você apenas fornece o servlet com alguns parâmetros para capturar o arquivo de imagem correto.

<img src="YourServlet?imageFileName=imageNum1">

Eu tinha um requisito: 1) não pode adicionar qualquer ?var=xx para a imagem 2) deve funcionar entre domínios

Eu realmente gosto da opção nº 4 nesta resposta com uma, mas:

  • ele tem problemas para trabalhar com crossdomain de forma confiável (e requer tocar no código do servidor).

Meu jeito rápido e sujo é:

  1. Criar iframe oculto
  2. Carregue a página atual para ela (sim, a página inteira)
  3. iframe.contentWindow.location.reload(true);
  4. Re-defina a fonte da imagem para si

Aqui 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);
}

Sim, eu sei, setTimeout ... Você tem que mudar isso para onload-events.


O que acabei fazendo foi fazer com que o servidor mapeasse qualquer pedido de uma imagem naquele diretório para a fonte que eu estava tentando atualizar. Em seguida, fiz com que meu timer acrescentasse um número ao final do nome para que o DOM o visualizasse como uma nova imagem e carregasse-o.

Por exemplo

http://localhost/image.jpg
//and
http://localhost/image01.jpg

solicitará o mesmo código de geração de imagem, mas parecerá com imagens diferentes para o 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);
}

Tente adicionar um cachebreaker no final do URL:

newImage.src = "http://localhost/image.jpg?" + new Date().getTime();

Isso anexará o registro de data e hora atual automaticamente quando você criar a imagem e fará com que o navegador olhe novamente para a imagem, em vez de recuperar aquela no cache.


Uma resposta é adicionar alguns parâmetros de consulta get como foi sugerido.

Uma resposta melhor é emitir algumas opções extras no cabeçalho HTTP.

Pragma: no-cache
Expires: Fri, 30 Oct 1998 14:19:41 GMT
Cache-Control: no-cache, must-revalidate

Ao fornecer uma data no passado, ela não será armazenada em cache pelo navegador. Cache-Control foi adicionado no HTTP / 1.1 e a tag must-revalidate indica que os proxies nunca devem servir uma imagem antiga mesmo sob circunstâncias atenuantes, e o Pragma: no-cache não é realmente necessário para os atuais navegadores / caches modernos, mas pode ajudar com algumas implementações antigas quebradas.


Eu usei o conceito abaixo de vincular primeiro a imagem com um URL falso (buffer) e vinculá-lo com o URL válido.

imgcover.ImageUrl = ConfigurationManager.AppSettings["profileLargeImgPath"] + "Myapp_CoverPic_" + userid + "Buffer.jpg";

imgcover.ImageUrl = ConfigurationManager.AppSettings["profileLargeImgPath"] + "Myapp_CoverPic_" + userid + ".jpg";

Dessa forma, estou forçando o navegador a atualizar com o URL válido.


Aqui está minha solução. É muito simples. O agendamento de quadros pode ser melhor.

<!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>

Fortemente baseado no código # 4 de Doin, o exemplo abaixo simplifica muito esse código utilizando em document.writevez de srcno iframeCORS. Também se concentra apenas em impedir o cache do navegador, não recarregando todas as imagens da página.

Abaixo está escrito em typescripte usa a biblioteca promessa angular $q , apenas fyi, mas deve ser fácil o suficiente para portar para o javascript de baunilha. O método destina-se a viver dentro de uma classe datilografada.

Retorna uma promessa que será resolvida quando o iframe for concluído. Não muito testado, mas funciona bem para nós.

    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);'>

Então abaixo em algum 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>

E assim, quando a imagem é carregada, ela é programada para ser recarregada em 1 segundo. Estou usando isso em uma página com câmeras de segurança doméstica de tipos variados.







refresh