Estou acessando um link no meu site que fornecerá uma nova imagem sempre que for acessada.
O problema que eu estou enfrentando é que, se eu tentar carregar a imagem em segundo plano e atualizar a imagem da 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
Preciso forçar uma atualização apenas dessa imagem na página. Alguma ideia?
javascript
image
url
refresh
QueueHammer
fonte
fonte
Respostas:
Tente adicionar um quebra-cache no final do URL:
Isso acrescentará o carimbo de data / hora atual automaticamente quando você estiver criando a imagem e fará com que o navegador procure novamente a imagem em vez de recuperar a que está no cache.
fonte
'image.jpg?' + (+new Date())
Date.now()
para issoMath.random()
Eu já vi muitas variações de respostas sobre como fazer isso, então pensei em resumi-las aqui (além de adicionar um quarto método de minha própria invenção):
(1) Adicione um parâmetro exclusivo de consulta de impedimento de cache ao URL, como:
Prós: 100% confiável, rápido e fácil de entender e implementar.
Contras: ignora completamente o cache, significando atrasos desnecessários e uso de largura de banda sempre que a imagem não muda entre as visualizações. Potencialmente preencherá o cache do navegador (e quaisquer caches intermediários) com muitas, muitas cópias da mesma imagem! Além disso, requer a modificação do URL da imagem.
Quando usar: use quando a imagem estiver mudando constantemente, como para um feed de webcam ao vivo. Se você usar esse método, certifique-se de veicular as imagens com
Cache-control: no-cache
cabeçalhos HTTP !!! (Geralmente, isso pode ser configurado usando um arquivo .htaccess). Caso contrário, você estará progressivamente preenchendo caches com versões antigas da imagem!(2) Adicione um parâmetro de consulta ao URL que muda apenas quando o arquivo é alterado, por exemplo:
(Esse é o código do lado do servidor PHP, mas o ponto importante aqui é apenas que uma string de consulta ? M = [hora da última modificação do arquivo] é anexada ao nome do arquivo).
Prós: 100% confiável, rápido e fácil de entender e implementar, e preserva perfeitamente as vantagens do cache.
Contras: Requer a modificação do URL da imagem. Além disso, um pouco mais de trabalho para o servidor - ele precisa ter acesso ao horário da última modificação do arquivo. Além disso, exige informações do lado do servidor, portanto, não é adequado para uma solução exclusivamente do lado do cliente verificar uma imagem atualizada.
Quando usar: quando você deseja armazenar em cache imagens, mas pode precisar atualizá-las periodicamente no servidor, sem alterar o nome do arquivo. E quando você pode garantir facilmente que a string de consulta correta seja adicionada a cada instância de imagem no seu HTML.
(3) Sirva suas imagens com o cabeçalho
Cache-control: max-age=0, must-revalidate
e adicione à URL um identificador de fragmento exclusivo para armazenamento de memcache , como:A idéia aqui é que o cabeçalho de controle de cache coloque imagens no cache do navegador, mas imediatamente as coloque obsoletas, para que, e sempre que sejam exibidas novamente, o navegador verifique com o servidor se elas foram alteradas. Isso garante que o cache HTTP do navegador sempre retorne a cópia mais recente da imagem. No entanto, os navegadores geralmente reutilizam uma cópia na memória de uma imagem, se tiverem uma, e nem mesmo verificam seu cache HTTP nesse caso. Para evitar isso, um identificador de fragmento é usado: A comparação das imagens na memória
src
inclui o identificador de fragmento, mas ele é retirado antes de consultar o cache HTTP. (Por exemplo,image.jpg#A
eimage.jpg#B
podem ser exibidos a partir daimage.jpg
entrada no cache HTTP do navegador, masimage.jpg#B
nunca seria exibido usando dados de imagem retidos na memória desde aimage.jpg#A
última vez que foi exibido).Prós: faz uso adequado dos mecanismos de cache HTTP e usa imagens em cache se elas não foram alteradas. Funciona para servidores que engasgam com uma string de consulta adicionada a uma URL de imagem estática (já que os servidores nunca veem identificadores de fragmento - eles são apenas para uso do próprio navegador).
Contras: Depende do comportamento um tanto duvidoso (ou pelo menos mal documentado) dos navegadores em relação às imagens com identificadores de fragmentos em seus URLs (no entanto, testei isso com êxito no FF27, Chrome33 e IE11). Ainda envia uma solicitação de revalidação ao servidor para cada exibição de imagem, o que pode ser um exagero se as imagens forem alteradas raramente e / ou a latência for um grande problema (pois é necessário aguardar a resposta de revalidação, mesmo quando a imagem em cache ainda estiver boa) . Requer a modificação de URLs de imagem.
Quando usar: use quando as imagens podem mudar com freqüência ou precisam ser atualizadas de forma intermitente pelo cliente, sem o envolvimento do script do servidor, mas onde você ainda deseja a vantagem do armazenamento em cache. Por exemplo, pesquisar uma webcam ao vivo que atualiza uma imagem irregularmente a cada poucos minutos. Como alternativa, use em vez de (1) ou (2) se o servidor não permitir cadeias de consulta em URLs de imagem estática.
(4) Atualize à força uma imagem específica usando Javascript, primeiro carregando-a em uma oculta
<iframe>
e depois chamandolocation.reload(true)
a iframecontentWindow
.Os passos são:
Carregue a imagem a ser atualizada em um iframe oculto. Esta é apenas uma etapa da configuração - pode ser feita com muito antecedência a atualização real, se desejado. Não importa se a imagem falha ao carregar nesta fase!
Feito isso, esvazie todas as cópias dessa imagem em suas páginas ou em qualquer lugar em qualquer nó DOM (mesmo fora da página armazenado em variáveis javascript). Isso é necessário porque o navegador pode exibir a imagem de uma cópia antiga na memória (o IE11 faz isso especialmente): É necessário garantir que todas as cópias na memória sejam limpas antes de atualizar o cache HTTP. Se outro código javascript estiver sendo executado de forma assíncrona, talvez você também precise impedir que esse código crie novas cópias da imagem a ser atualizada enquanto isso.
Ligue
iframe.contentWindow.location.reload(true)
. Astrue
forças de um desvio cache, recarregar diretamente do servidor e substituindo a cópia em cache existente.Assim que terminar re -loading, restaurar as imagens em branco. Agora eles devem exibir a versão nova do servidor!
Para imagens do mesmo domínio, você pode carregar a imagem diretamente no iframe. Para imagens entre domínios, você deve carregar uma página HTML do seu domínio que contenha a imagem em uma
<img>
tag, caso contrário, você receberá um erro "Acesso negado" ao tentar ligariframe.contentWindow.reload(...)
.Prós: Funciona exatamente como a função image.reload () que você deseja que o DOM possua ! Permite que as imagens sejam armazenadas em cache normalmente (mesmo com datas de validade futuras, se você as desejar, evitando assim a revalidação frequente). Permite atualizar uma imagem específica sem alterar os URLs dessa imagem na página atual ou em qualquer outra página, usando apenas o código do lado do cliente.
Contras: depende de Javascript. Não é 100% garantido que funcione corretamente em todos os navegadores (embora eu tenha testado isso com êxito no FF27, Chrome33 e IE11). Muito complicado em relação aos outros métodos.
Quando usar: quando você tem uma coleção de imagens basicamente estáticas que deseja armazenar em cache, mas ainda precisa atualizá-las ocasionalmente e obter feedback visual imediato de que a atualização ocorreu. (Especialmente quando apenas atualizar a página inteira do navegador não funcionaria, como em alguns aplicativos da Web criados no AJAX, por exemplo). E quando os métodos (1) - (3) não são viáveis, porque (por qualquer motivo) você não pode alterar todos os URLs que podem exibir a imagem que você precisa atualizar. (Observe que, usando esses três métodos, a imagem será atualizada, mas se outra página tentar exibir essa imagem sem a string de consulta ou o identificador de fragmento apropriado, ela poderá mostrar uma versão mais antiga).
Os detalhes de implementar isso de uma maneira robusta e flexível são dados abaixo:
Vamos supor que seu site contenha .gif em branco de 1x1 pixel no caminho da URL
/img/1x1blank.gif
e também tenha o seguinte script PHP de uma linha (necessário apenas para aplicar atualização forçada a imagens entre domínios) e pode ser reescrito em qualquer linguagem de script do lado do servidor , é claro) no caminho da URL/echoimg.php
:Então, aqui está uma implementação realista de como você pode fazer tudo isso em Javascript. Parece um pouco complicado, mas há muitos comentários, e a função importante é apenas forceImgReload () - as duas primeiras imagens em branco e não em branco, e devem ser projetadas para funcionar eficientemente com seu próprio HTML, codifique-as como funciona melhor para você; muitas das complicações nelas podem ser desnecessárias para o seu site:
Em seguida, para forçar uma atualização de uma imagem localizada no mesmo domínio da sua página, você pode:
Para atualizar uma imagem de outro lugar (entre domínios):
Um aplicativo mais avançado pode ser recarregar uma imagem após o upload de uma nova versão para o servidor, preparando o estágio inicial do processo de recarregamento simultaneamente com o upload, para minimizar o atraso visível do recarregamento para o usuário. Se você estiver fazendo o upload via AJAX, e o servidor estiver retornando uma matriz JSON muito simples [sucesso, largura, altura], seu código poderá se parecer com o seguinte:
Uma observação final: embora este tópico seja sobre imagens, ele também se aplica a outros tipos de arquivos ou recursos. Por exemplo, impedindo o uso de scripts obsoletos ou arquivos css, ou mesmo atualizando documentos PDF atualizados (usando (4) somente se configurado para abrir no navegador). O método (4) pode exigir algumas alterações no javascript acima, nesses casos.
fonte
image.jpg#123
paraimage.jpg#124
(ou qualquer outra coisa, desde que o bit após o '#' seja alterado). Você poderia esclarecer o que está recarregando e por quê?contentWindow
via javascript para fazer areload(true)
chamada, que é a parte crítica do método ... então não, método (4 ) não funcionará para conteúdo entre domínios. Bem manchado; Vou atualizar os "Contras" para incluir isso.Como alternativa para ...
...parece que...
... é suficiente para enganar o cache do navegador sem ignorar os caches upstream, assumindo que você retornou os
Cache-Control
cabeçalhos corretos . Embora você possa usar ...... você perde os benefícios dos cabeçalhos
If-Modified-Since
ouIf-None-Match
, então algo como ...... deve impedir o navegador de baixar novamente a imagem inteira, se ela não tiver sido realmente alterada. Testado e funcionando no IE, Firefox e Chrome. Irritantemente, ele falha no Safari, a menos que você use ...
... embora isso ainda possa ser preferível ao preenchimento de caches upstream com centenas de imagens idênticas, principalmente quando elas estão sendo executadas em seu próprio servidor. ;-)
Atualização (28-09-2014): hoje em dia parece
Cache-Control: no-store
ser necessário também para o Chrome.fonte
src
atributo completo , portanto, adicionar um identificador de fragmento exclusivo garante que a imagem não seja simplesmente retirada da memória. Mas os identificadores de fragmento não são enviados como parte das solicitações HTTP, portanto, o cache HTTP comum será usado normalmente. É por isso que essa técnica funciona.Cache-Control: max-age=0, must-revalidate
é bom pra mim?newImage.src = "http://localhost/image.jpg#" + i++;
Depois de criar a nova imagem, você está removendo a imagem antiga do DOM e substituindo-a pela nova?
Você pode pegar novas imagens a cada chamada updateImage, mas não adicioná-las à página.
Existem várias maneiras de fazer isso. Algo assim iria funcionar.
Depois de fazer isso funcionar, se ainda houver problemas, provavelmente é um problema de cache, como as outras respostas mencionam.
fonte
Uma resposta é adicionar hackishly algum parâmetro get query como foi sugerido.
Uma resposta melhor é emitir algumas opções extras no seu cabeçalho HTTP.
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 exibir uma imagem antiga, mesmo em circunstâncias atenuantes, e issoPragma: no-cache
não é realmente necessário para os navegadores / caches modernos atuais, mas pode ajudar com algumas implementações antigas e quebradas.fonte
Eu tinha um requisito: 1) não pode adicionar nenhum
?var=xx
à imagem 2) deve funcionar em vários domíniosEu realmente gosto da opção # 4 nesta resposta com uma, mas:
Minha maneira rápida e suja é:
iframe.contentWindow.location.reload(true);
Aqui está
Sim, eu sei, setTimeout ... Você precisa mudar isso para eventos onload apropriados.
fonte
Então abaixo em algum javascript
E o que isso faz é que, quando a imagem é carregada, a agenda é recarregada em 1 segundo. Estou usando isso em uma página com câmeras de segurança doméstica de tipos variados.
fonte
Acabei fazendo o servidor mapear qualquer solicitação de imagem nesse diretório para a fonte que eu estava tentando atualizar. Depois, meu cronômetro anexou um número ao final do nome para que o DOM o visse como uma nova imagem e o carregasse.
Por exemplo
solicitará o mesmo código de geração de imagens, mas parecerá imagens diferentes para o navegador.
fonte
fonte
../showImage.phpFri May 01 2015 17:34:18 GMT+0200 (Mitteleuropäische Sommerzeit)
é um nome de arquivo válido ... Pelo menos é isso que ele tenta carregar ...path='../showImage.php';
parapath='../showImage.php?';
defina seu próprio src como seu src.
fonte
Tente usar uma string de consulta sem valor para torná-la um URL exclusivo:
fonte
Altamente baseado no código # 4 de Doin, o exemplo abaixo simplifica bastante esse código, em
document.write
vez desrc
noiframe
suporte ao CORS. Também se concentra apenas em bloquear o cache do navegador, e não recarregar todas as imagens na página.Abaixo está escrito
typescript
e usa a biblioteca de promessaangular
$ q , apenas fyi, mas deve ser fácil o suficiente para portar para javascript vanilla. O método deve viver dentro de uma classe de texto datilografado.Retorna uma promessa que será resolvida quando o iframe concluir o recarregamento. Não é muito testado, mas funciona bem para nós.
fonte
+ encodeURI(src) +
corretamente para escaparsrc
noiframe
.O código a seguir é útil para atualizar a imagem quando um botão é clicado.
fonte
Resolvi esse problema enviando os dados de volta através de um servlet.
Em seguida, na página, você fornece o servlet com alguns parâmetros para obter o arquivo de imagem correto.
fonte
Aqui está a minha solução. É muito simples. O agendamento de quadros poderia ser melhor.
fonte
Não há necessidade de
new Date().getTime()
travessuras. Você pode enganar o navegador tendo uma imagem fictícia invisível e usando jQuery .load () e, em seguida, criando uma nova imagem a cada vez:fonte
Solução simples: adicione este cabeçalho à resposta:
Por que isso funciona é explicado claramente nesta página oficial : https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
Também explica por
no-cache
que não funciona.Outras respostas não funcionam porque:
Caching.delete
é sobre um novo cache que você pode criar para trabalhos off-line, consulte: https://web.dev/cache-api-quick-guide/Fragmentos que usam um # no URL não funcionam porque o # diz ao navegador para não enviar uma solicitação ao servidor.
Um cache-buster com uma parte aleatória adicionada ao URL funciona, mas também preencherá o cache do navegador. No meu aplicativo, eu queria baixar uma imagem de 5 MB a cada segundo de uma webcam. Vai demorar apenas uma hora ou menos para congelar completamente o seu PC. Ainda não sei por que o cache do navegador não se limita a um máximo razoável, mas isso é definitivamente uma desvantagem.
fonte
Melhorei o script do AlexMA para mostrar minha webcam em uma página da web que periodicamente carrega uma nova imagem com o mesmo nome. Eu tive problemas que às vezes a imagem tremia por causa de uma imagem quebrada ou por uma imagem carregada (incompleta). Para evitar oscilações, verifico a altura natural da imagem porque o tamanho da imagem da minha webcam não mudou. Somente se a altura da imagem carregada corresponder à altura da imagem original, a imagem completa será mostrada na página.
fonte
Eu usei o conceito abaixo de primeiro vincular a imagem com um URL falso (buffer) e depois vinculá-lo ao URL válido.
Dessa forma, estou forçando o navegador a atualizar com um URL válido.
fonte