Desative o cache para algumas imagens

113

Eu gero algumas imagens usando um lib PHP.

Às vezes, o navegador não carrega o novo arquivo gerado.

Como posso desativar o cache apenas para imagens criadas dinamicamente por mim?

Nota: tenho que usar o mesmo nome para as imagens criadas ao longo do tempo.

dole doug
fonte

Respostas:

233

Uma solução comum e simples para esse problema que parece um hack, mas é bastante portátil, é adicionar uma string de consulta gerada aleatoriamente a cada solicitação da imagem dinâmica.

Então, por exemplo -

<img src="image.png" />

Se tornaria

<img src="image.png?dummy=8484744" />

Ou

<img src="image.png?dummy=371662" />

Do ponto de vista do servidor web, o mesmo arquivo é acessado, mas do ponto de vista do navegador, nenhum cache pode ser executado.

A geração do número aleatório pode acontecer no servidor ao servir a página (apenas certifique-se de que a página em si não está em cache ...) ou no cliente (usando JavaScript).

Você precisará verificar se o seu servidor web pode lidar com esse truque.

Hexágono
fonte
87
Em vez de números aleatórios, use o carimbo de data / hora em que os dados foram alterados ou um número de versão dos dados refletidos.
lhunath,
19
Observação: você não impede que o navegador armazene a imagem em cache, apenas evita olhar para a imagem em cache. Aplicar cabeçalhos adequados à sua imagem é a melhor maneira imho (veja a solução de lhunath abaixo). Visto que dessa forma você também preenche o cache desnecessariamente com imagens que não deseja armazenar em cache, com o custo de causar menos espaço de cache para coisas que você realmente deseja que sejam armazenadas em cache.
Jos
Acredito que este artigo explique o motivo de tal comportamento.
Metalcoder
1
isso não funciona realmente, a imagem precisa ser limpa de outra maneira (geralmente no corte da imagem, a imagem permanece a mesma)
Ben
44

As estratégias de cache do navegador podem ser controladas por cabeçalhos HTTP. Lembre-se de que eles são apenas uma dica, na verdade. Como os navegadores são terrivelmente inconsistentes neste (e em qualquer outro) campo, você precisará de vários cabeçalhos para obter o efeito desejado em uma variedade de navegadores.

header ("Pragma-directive: no-cache");
header ("Cache-directive: no-cache");
header ("Cache-control: no-cache");
header ("Pragma: no-cache");
header ("Expires: 0");
lhunath
fonte
1
isso se aplicará a toda a página .... Não consigo desativar o cache para apenas uma imagem (uma imagem específica dessa página)?
dole doug
5
@Thorpe: aplica-se a respostas HTTP. O que está contido na resposta é irrelevante. Quer se trate de dados de imagem, dados HTML ou qualquer outra coisa. Se não funcionou, provavelmente você não fez direito. Verifique os cabeçalhos HTTP em sua resposta para ver se eles foram atribuídos corretamente.
lhunath
Gostaria que funcionasse ... O Chrome não tem problemas, mas o Firefox 14 e o IE 8 se recusam a atualizar as imagens, mesmo com os cabeçalhos acima sendo enviados. Isso teria sido uma solução muito mais limpa do que adicionar alguns parâmetros arbitrários à string de consulta. suspiro
Pawel Krakowiak
2
@PawelKrakowiak Observe que adicionar cabeçalhos não funcionará para imagens que estão em cache , uma vez que o navegador nem mesmo pergunta ao servidor sobre eles e, portanto, nunca verá os cabeçalhos. Eles funcionarão para qualquer solicitação de imagem feita após você adicioná-los.
lhunath de
2
Esta solução é destinada a programadores, não a web designers. Pensei em apontar isso porque não se pode simplesmente abrir uma imagem e adicionar cabeçalhos a uma imagem, a menos que eles próprios estejam gerando a imagem em uma linguagem de programação e isso parece confundir os comentadores.
Bruce
13

Se você precisa fazer isso dinamicamente no navegador usando javascript, aqui está um exemplo ...

<img id=graph alt="" 
  src="http://www.kitco.com/images/live/gold.gif" 
  />

<script language="javascript" type="text/javascript">
    var d = new Date(); 
    document.getElementById("graph").src = 
      "http://www.kitco.com/images/live/gold.gif?ver=" + 
       d.getTime();
</script>
Anton Swanevelder
fonte
12

A solução 1 não é ótima. Funciona, mas adicionar strings de consulta aleatórias ou com carimbo de data / hora ao final dos arquivos de imagem fará com que o navegador baixe novamente e armazene em cache todas as versões de todas as imagens, sempre que uma página for carregada, independentemente do clima em que a imagem tenha mudado ou não no servidor.

A solução 2 é inútil. Adicionar nocachecabeçalhos a um arquivo de imagem não é apenas muito difícil de implementar, mas também é totalmente impraticável porque exige que você preveja quando será necessário com antecedência , a primeira vez que você carrega qualquer imagem que você acha que pode mudar em algum momento no futuro .

Entrar Etags ...

A melhor maneira que encontrei de resolver isso é usar ETAGS dentro de um arquivo .htaccess no diretório de imagens. O seguinte diz ao Apache para enviar um hash exclusivo para o navegador nos cabeçalhos do arquivo de imagem. Esse hash só muda quando o arquivo de imagem é modificado e essa mudança aciona o navegador para recarregar a imagem na próxima vez que for solicitada.

<FilesMatch "\.(jpg|jpeg)$">
FileETag MTime Size
</FilesMatch>
cronoklee
fonte
11

Verifiquei todas as respostas e a melhor parecia ser (que não é):

<img src="image.png?cache=none">

no início.

No entanto, se você adicionar o parâmetro cache = none (que é a palavra "none" estática), isso não afetará nada, o navegador ainda carrega do cache.

A solução para este problema foi:

<img src="image.png?nocache=<?php echo time(); ?>">

onde você basicamente adiciona um carimbo de data / hora Unix para tornar o parâmetro dinâmico e sem cache, funcionou.

No entanto, meu problema era um pouco diferente: eu estava carregando a imagem de gráfico php gerada em tempo real e controlando a página com os parâmetros $ _GET. Eu queria que a imagem fosse lida do cache quando o parâmetro GET da URL permanecesse o mesmo e não fizesse cache quando os parâmetros GET mudassem.

Para resolver esse problema, eu precisava fazer o hash $ _GET, mas como é um array, aqui está a solução:

$chart_hash = md5(implode('-', $_GET));
echo "<img src='/images/mychart.png?hash=$chart_hash'>";

Editar :

Embora a solução acima funcione bem, às vezes você deseja servir a versão em cache ATÉ que o arquivo seja alterado. (com a solução acima, ele desativa o cache para aquela imagem completamente) Então, para servir a imagem em cache do navegador ATÉ que haja uma mudança no uso do arquivo de imagem:

echo "<img src='/images/mychart.png?hash=" . filemtime('mychart.png') . "'>";

filemtime () obtém a hora de modificação do arquivo.

Tarik
fonte
4

Eu sei que este tópico é antigo, mas se classifica muito bem no Google. Descobri que colocar isso no cabeçalho funciona bem;

<meta Http-Equiv="Cache-Control" Content="no-cache">
<meta Http-Equiv="Pragma" Content="no-cache">
<meta Http-Equiv="Expires" Content="0">
<meta Http-Equiv="Pragma-directive: no-cache">
<meta Http-Equiv="Cache-directive: no-cache">
Dimitri Visser
fonte
Navegadores modernos infelizmente estão ignorando essas diretivas, portanto esta solução pode funcionar apenas em alguns navegadores, também, irá desativar o cache para tudo, não apenas para imagens específicas
ZioCain
4

Eu estava apenas procurando uma solução para isso e as respostas acima não funcionaram no meu caso (e não tenho reputação suficiente para comentar sobre elas). Acontece que, pelo menos para meu caso de uso e o navegador que eu estava usando (Chrome no OSX), a única coisa que parecia impedir o cache era:

Cache-Control = 'no-store'

Para completar, agora estou usando todos os 3 'no-cache, no-store, must-revalidate'

Portanto, no meu caso (veiculando imagens geradas dinamicamente fora do Flask em Python), tive que fazer o seguinte para, com sorte, trabalhar no maior número de navegadores possível ...

def make_uncached_response(inFile):
    response = make_response(inFile)
    response.headers['Pragma-Directive'] = 'no-cache'
    response.headers['Cache-Directive'] = 'no-cache'
    response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
    response.headers['Pragma'] = 'no-cache'
    response.headers['Expires'] = '0'
    return response
Marca
fonte
Apenas não guardar a resposta foi o suficiente para fazê-la funcionar para mim
flagelo 192
Não é apenas no Chrome, também para o Firefox. Parece ser um padrão agora: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control (consulte a seção " Prevenção de cache ").
Gino Mempin
3

Mudar a fonte da imagem é a solução. Você realmente pode fazer isso adicionando um carimbo de data / hora ou um número aleatório à imagem.

Melhor seria adicionar uma soma de verificação, por exemplo, dos dados que a imagem representa. Isso habilita o cache quando possível.

Stefan van Gastel
fonte
1

Vamos adicionar outra solução ao grupo.

Adicionar uma string exclusiva no final é a solução perfeita.

example.jpg?646413154

A solução a seguir estende este método e fornece a capacidade de armazenamento em cache e busca uma nova versão quando a imagem é atualizada.

Quando a imagem for atualizada, o tempo de filmagem será alterado.

<?php
$filename = "path/to/images/example.jpg";
$filemtime = filemtime($filename);
?>

Agora produza a imagem:

<img src="images/example.jpg?<?php echo $filemtime; ?>" >
Daniel
fonte
1
Isso é o que usei por causa da validade do cache.
gene
1

eu tive esse problema e superando assim.

var newtags='<div class="addedimage"><h5>preview image</h5><img src="'+one+'?nocache='+Math.floor(Math.random() * 1000)+'"></div>';
Jordan Georgiadis
fonte
0

Usei isso para resolver meu problema semelhante ... exibindo um contador de imagens (de um provedor externo). Nem sempre foi atualizado corretamente. E depois que um parâmetro aleatório foi adicionado, tudo funciona bem :)

Anexei uma string de data para garantir a atualização pelo menos a cada minuto.

código de amostra (PHP):

$output .= "<img src=\"http://xy.somecounter.com/?id=1234567890&".date(ymdHi)."\" alt=\"somecounter.com\" style=\"border:none;\">";

Isso resulta em um srclink como:

http://xy.somecounter.com/?id=1234567890&1207241014
Pinoccio
fonte
0

Se você tiver um URL de imagem codificado, por exemplo: http://example.com/image.jpg, você pode usar php para adicionar cabeçalhos à sua imagem.

Primeiro você terá que fazer o apache processar seu jpg como php. Veja aqui: É possível executar PHP com extensão file.php.jpg?

Carregue a imagem (imagecreatefromjpeg) do arquivo e adicione os cabeçalhos das respostas anteriores. Use o cabeçalho da função php para adicionar os cabeçalhos.

Em seguida, produza a imagem com a função imagejpeg.

Observe que é muito inseguro permitir que php processe imagens jpg. Além disso, esteja ciente de que não testei essa solução, portanto, depende de você fazer com que funcione.

Sam Sam
fonte
-1

Simples, envie um local de cabeçalho.

Meu site, contém uma imagem, e após fazer o upload da imagem, não muda, então adiciono este código:

<?php header("Location: pagelocalimage.php"); ?>

Funciona para mim.

Programador
fonte