Pergunta

Fundo

Eu estou escrevendo e usando uma ferramenta (Perl) de gerenciamento de conteúdo baseado em CGI muito simples para duas pro-bono websites. Ele fornece o administrador do site com formulários HTML para eventos onde eles enchem os campos (data, local, título, descrição, links, etc.) e salvá-lo. Nessa forma eu permitir que o administrador para fazer upload de uma imagem relacionada ao evento. Na página HTML exibir o formulário, eu também estou mostrando uma visualização da imagem carregada (HTML img tag).

O Problema

O problema acontece quando o administrador quer mudar a imagem. Ele simplesmente tem que bater no botão "Procurar", escolher uma nova imagem e pressione ok. E isso funciona bem.

Uma vez que a imagem é carregada, meus back-end CGI alças o upload e recarrega o formulário corretamente.

O problema é que a imagem mostrada não se refrescou. A imagem antiga ainda é mostrado, embora o banco de dados contém a imagem certa. Eu reduzi-lo para o fato de que a imagem é armazenada em cache no navegador da web. Se o administrador clicar no botão RELOAD no Firefox / Explorador / Safari, tudo fica bem atualizada e a nova imagem apenas aparece.

My Solution - não funciona

Eu estou tentando controlar o cache escrevendo uma instrução HTTP Expira com uma data muito distante no passado.

Expires: Mon, 15 Sep 2003 1:00:00 GMT

Lembre-se que eu estou do lado administrativo e eu realmente não me importo se as páginas demora um pouco mais a carga, porque eles estão sempre expirado.

Mas, isso não quer trabalhar.

Notas

Ao fazer upload de uma imagem, seu nome de arquivo não é mantido no banco de dados. Ele é renomeado como Image.jpg (para simplesmente as coisas quando usá-lo). Ao substituir a imagem existente por um novo, o nome não muda tanto. Apenas o conteúdo das mudanças de arquivo de imagem.

O servidor web é fornecido pelo serviço de hospedagem / ISP. Ele usa Apache.

Pergunta

Existe uma maneira de forçar o navegador para não armazena em cache as coisas desta página, nem mesmo imagens?

Estou fazendo malabarismos com a opção de realmente "salvar o nome do arquivo" com o banco de dados. Desta forma, se a imagem for alterado, o src da tag IMG também vai mudar. No entanto, isso requer uma série de mudanças em todo o site e eu prefiro não fazê-lo se eu tiver uma solução melhor. Além disso, este irá ainda não trabalho se a nova imagem carregada tem o mesmo nome (digamos, a imagem é photoshopped um pouco e re-carregado).

Foi útil?

Solução

Armin Ronacher tem a idéia correta. O problema é seqüências aleatórias podem colidir. Eu usaria:

<img src="picture.jpg?1222259157.415" alt="">

Onde "1222259157.415" é o momento atual no servidor.
Gerar tempo, Javascript com performance.now() ou Python com time.time()

Outras dicas

correção simples: Anexar uma string de consulta aleatória para a imagem:

<img src="foo.cgi?random=323527528432525.24234" alt="">

O que a RFC HTTP diz:

Cache-Control: no-cache

Mas que não funciona tão bem:)

Eu uso do PHP arquivo modificado tempo função , por exemplo:

echo <img  src='Images/image.png?" . filemtime('Images/image.png') . "'  />";

Se você alterar a imagem, em seguida, a nova imagem é usada em vez de um cache, devido a ter um timestamp modificado diferente.

Gostaria de usar:

<img src="picture.jpg?20130910043254">

onde "20130910043254" é o tempo de modificação do arquivo.

Ao fazer upload de uma imagem, seu nome de arquivo não é mantido no banco de dados. Ele é renomeado como Image.jpg (para simplesmente as coisas quando usá-lo). Ao substituir a imagem existente por um novo, o nome não muda tanto. Apenas o conteúdo das mudanças de arquivo de imagem.

Eu acho que existem dois tipos de soluções simples: 1) os que vêm à mente primeiro (soluções simples, porque eles são fáceis de chegar a), 2) os que você acabar com depois que as coisas de pensamento mais (porque eles são fáceis de usar). Aparentemente, você não vai sempre beneficiar se você escolheu para pensar sobre as coisas. Mas a segunda opções é bastante subestimado, eu acredito. Basta pensar por que php é tão popular;)

Você pode escrever um script de proxy para servir imagens - que é um pouco mais do trabalho embora. Algo gosta este:

HTML:

<img src="image.php?img=imageFile.jpg&some-random-number-262376" />

Script:

// PHP
if( isset( $_GET['img'] ) && is_file( IMG_PATH . $_GET['img'] ) ) {

  // read contents
  $f = open( IMG_PATH . $_GET['img'] );
  $img = $f.read();
  $f.close();

  // no-cache headers - complete set
  // these copied from [php.net/header][1], tested myself - works
  header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Some time in the past
  header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); 
  header("Cache-Control: no-store, no-cache, must-revalidate"); 
  header("Cache-Control: post-check=0, pre-check=0", false); 
  header("Pragma: no-cache"); 

  // image related headers
  header('Accept-Ranges: bytes');
  header('Content-Length: '.strlen( $img )); // How many bytes we're going to send
  header('Content-Type: image/jpeg'); // or image/png etc

  // actual image
  echo $img;
  exit();
}
cabeçalhos

Na verdade, quer no-cache ou número aleatório na imagem src deve ser suficiente, mas desde que nós queremos ser à prova de bala ..

Sou um novo Coder, mas aqui está o que eu vim com, para parar o navegador de cache e segurando meus pontos de vista da webcam:

<meta Http-Equiv="Cache" content="no-cache">
<meta Http-Equiv="Pragma-Control" content="no-cache">
<meta Http-Equiv="Cache-directive" Content="no-cache">
<meta Http-Equiv="Pragma-directive" Content="no-cache">
<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">

Não tenho certeza o que funciona sobre o navegador, mas ela não funciona para alguns: IE: Funciona quando página é atualizada e quando o site é revisitado (sem atualização). Chrome: Works somente quando página é atualizada (mesmo após uma nova visita). SAFARI e iPad: não funciona, eu tenho que limpar o Histórico e Web Data .

Todas as ideias sobre / iPad SAFARI?

uso class = "NO-CACHE"

html de exemplo:

<div>
    <img class="NO-CACHE" src="images/img1.jpg" />
    <img class="NO-CACHE" src="images/imgLogo.jpg" />
</div>

jQuery:

    $(document).ready(function ()
    {           
        $('.NO-CACHE').attr('src',function () { return $(this).attr('src') + "?a=" + Math.random() });
    });

javascript:

var nods = document.getElementsByClassName('NO-CACHE');
for (var i = 0; i < nods.length; i++)
{
    nods[i].attributes['src'].value += "?a=" + Math.random();
}

Resultado: src = "images / img1.jpg" => src = "images / img1.jpg? a = ,08749723793963926"

Ao fazer upload de uma imagem, seu nome de arquivo não é mantido no banco de dados. Ele é renomeado como Image.jpg (para simplesmente as coisas quando usá-lo).

mudar isso, e você fixa o seu problema. Eu uso timestamps, como acontece com as soluções propostas acima: Imagem- .jpg

Presumivelmente, o que problemas você está evitando, mantendo o mesmo nome para a imagem pode ser superado, mas você não diz o que são.

Eu verifiquei todas as respostas em torno da web e um dos melhores parecia ser: (na verdade, não é)

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

em primeiro lugar.

No entanto, se você adicionar cache = nenhuma parâmetro (que é estático "none" palavra), não faz efeito nada, navegador ainda grande quantidade de cache.

solução para este problema foi:

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

onde você basicamente adicionar unix timestamp para fazer a dinâmica de parâmetros e sem cache, funcionou.

No entanto, o meu problema era um pouco diferente: Eu estava carga sobre a imagem do gráfico php mosca gerado, e controlando a página com $ _GET parâmetros. Eu queria que a imagem para ser lido do cache quando as estadias de parâmetros URL obter o mesmo, e não cache quando a mudança parâmetros GET.

Para resolver este problema, eu precisava de hash $ _GET, mas uma vez que é gama 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 funciona muito bem, às vezes você quer servir a versão em cache até que o arquivo é alterado. (Com a solução acima, que desactiva o cache para essa imagem completamente) Assim, para servir de 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 o tempo de modificação do arquivo.

Seu problema é que, apesar do cabeçalho Expires:, o navegador é re-utilizando a sua cópia de memória em da imagem da antes de ser atualizado, em vez de mesmo verificar a sua cache.

Eu tinha imagens de produtos situação upload muito similares no backend de administração para uma loja-como local, e no meu caso eu decidi que a melhor opção era usar javascript para forçar uma atualização de imagem, sem o uso de qualquer um dos URL modificadora técnicas de outras pessoas já mencionados aqui. Em vez disso, colocar o URL da imagem em um iframe oculto, chamado location.reload(true) na janela do IFRAME, e depois substituído minha imagem na página. Este forças uma atualização da imagem, não apenas sobre a página que eu sou, mas também em todas as páginas posteriores I visitar -. Sem qualquer cliente ou servidor ter que lembrar de qualquer querystring URL ou parâmetros fragmento identificador

Eu postei algum código para fazer isso na minha resposta aqui .

Adicionar um <img src="picture.jpg?t=<?php echo time();?>"> carimbo de tempo

sempre dar o seu arquivo de um número aleatório no final e pará-lo cache

Com o potencial para mal comportado proxies transparentes em entre você eo cliente, a única maneira de totalmente garantia de que as imagens não serão armazenados em cache é dar-lhes um URI exclusivo, algo como marcação de um timestamp como um string de consulta ou como parte do caminho.

Se que corresponde timestamp para o último tempo de atualização da imagem, então você pode armazenar em cache quando você precisa e servir a nova imagem no momento certo.

Eu assumo originais pergunta diz respeito às imagens armazenadas com algumas informações de texto. Então, se você tiver acesso a um contexto do texto ao gerar src = ... url, considere estoque / uso CRC32 da imagem bytes em vez de sentido selo aleatória ou tempo. Então, se a página com uma abundância de imagens está exibindo, apenas imagens atualizados serão recarregados. Eventualmente, se CRC armazenamento é impossível, pode ser computada e anexada ao URL em tempo de execução.

Do meu ponto de vista, desative imagens caching é uma má idéia. Em absoluto.

A raiz do problema aqui é - como forçar navegador de imagem de atualização para, quando ele foi atualizado em um lado do servidor.

Mais uma vez, do meu ponto de vista pessoal, a melhor solução é a de acesso directo desativar a imagens. imagens em vez de acesso através do filtro do lado do servidor / servlet / outras ferramentas similares / serviços.

No meu caso é um que a imagem retorna e anexa ETag em resposta serviço resto,. O serviço mantém de hash de todos os arquivos, se o arquivo for alterado, hash é atualizado. Ele funciona perfeitamente em todos os navegadores modernos. Sim, é preciso tempo para implementá-lo, mas que vale a pena.

A única exceção - são favicons. Por algumas razões, ele não funciona. Eu não poderia forçar o navegador para atualizar seu cache do lado do servidor. ETags, Cache Control, expira, cabeçalhos Pragma, nada ajudou.

Neste caso, a adição de algum parâmetro aleatório / versão em url, ao que parece, é a única solução.

Idealmente, você deve adicionar um / atalho de teclado / botão de menu para cada página com uma opção para o conteúdo de sincronização.

Para fazer isso, você iria manter o controle de recursos que podem precisar de ser sincronizados, e tanto para uso xhr para sondar as imagens com uma querystring dinâmico, ou criar uma imagem em tempo de execução com src usando uma querystring dinâmico. Em seguida, use um mecanismo de transmissão para notificar todos componentes das páginas que estão usando o recurso de atualização para usar o recurso com uma dinâmica queryString anexa à sua url.

Um exemplo ingênuos esta aparência:

Normalmente, a imagem é exibida e em cache, mas se o usuário pressionou o botão, um pedido de xhr é enviado para o recurso com uma querystring tempo anexado a ele; uma vez que o tempo pode ser assumido como sendo diferente em cada imprensa, que irá certificar-se de que o navegador irá limpar a cache, uma vez que não pode dizer se o recurso é gerado dinamicamente no lado do servidor com base na consulta, ou se é uma estática recurso que consulta ignora.

O resultado é que você pode evitar ter todos os seus usuários bombardeá-lo com recurso solicita o tempo todo, mas, ao mesmo tempo, permitir que um mecanismo para que os usuários atualizem seus recursos, se eles suspeitam que eles estão fora de sincronia.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="mobile-web-app-capable" content="yes" />        
    <title>Resource Synchronization Test</title>
    <script>
function sync() {
    var xhr = new XMLHttpRequest;
    xhr.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {            
            var images = document.getElementsByClassName("depends-on-resource");

            for (var i = 0; i < images.length; ++i) {
                var image = images[i];
                if (image.getAttribute('data-resource-name') == 'resource.bmp') {
                    image.src = 'resource.bmp?i=' + new Date().getTime();                
                }
            }
        }
    }
    xhr.open('GET', 'resource.bmp', true);
    xhr.send();
}
    </script>
  </head>
  <body>
    <img class="depends-on-resource" data-resource-name="resource.bmp" src="resource.bmp"></img>
    <button onclick="sync()">sync</button>
  </body>
</html>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top