Bazı görüntüler için önbelleği devre dışı bırakın


113

PHP kitaplığı kullanarak bazı görüntüler oluşturuyorum.

Bazen tarayıcı yeni oluşturulan dosyayı yüklemez.

Yalnızca benim tarafımdan dinamik olarak oluşturulan görüntüler için önbelleği nasıl devre dışı bırakabilirim?

Not: Oluşturulan görseller için zamanla aynı adı kullanmam gerekiyor.

Yanıtlar:


233

Bu soruna bilgisayar korsanlığı gibi görünen ancak oldukça taşınabilir olan yaygın ve basit bir çözüm, dinamik görüntü için her isteğe rastgele oluşturulmuş bir sorgu dizesi eklemektir.

Yani mesela -

<img src="image.png" />

Olacaktı

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

Veya

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

Web sunucusunun bakış açısından aynı dosyaya erişilir, ancak tarayıcının bakış açısından hiçbir önbelleğe alma gerçekleştirilemez.

Rastgele sayı üretimi, sayfayı sunarken sunucuda (sayfanın kendisinin önbelleğe alınmadığından emin olun ...) veya istemcide (JavaScript kullanarak) gerçekleşebilir.

Web sunucunuzun bu numara ile baş edip edemeyeceğini doğrulamanız gerekecektir.


87
Rastgele sayılar yerine, verilerin değiştiği zaman damgasını veya yansıtılan verilerin sürüm numarasını kullanın.
lhunath


19
Lütfen dikkat: Tarayıcının resmi önbelleğe almasını gerçekten engellemezsiniz, yalnızca önbelleğe alınan görüntüye bakmayı engellersiniz. Resminize uygun başlıkları uygulamak en iyi yoldur (aşağıdaki lhunath çözümüne bakın). Bu şekilde, önbelleği gereksiz yere görüntülerle de doldurduğunuzdan, gerçekten önbelleğe alınmasını istediğiniz şeyler için daha az önbellek alanı oluşturma maliyetiyle önbelleğe almak istemezsiniz.
Jos

Bu makalenin bu tür davranışların nedenini açıkladığına inanıyorum .
Metalcoder

1
bu gerçekten işe yaramıyor, görüntünün başka bir şekilde yıkanması gerekiyor (genellikle görüntü kırpılırken görüntü aynı kalır)
Ben

44

Tarayıcı önbelleğe alma stratejileri, HTTP başlıkları tarafından kontrol edilebilir. Unutma ki bunlar sadece bir ipucu, gerçekten. Tarayıcılar bu (ve başka herhangi bir alanda) son derece tutarsız olduğundan, çeşitli tarayıcılarda istenen etkiyi elde etmek için birkaç başlığa ihtiyacınız olacak.

header ("Pragma-directive: no-cache");
header ("Cache-directive: no-cache");
header ("Cache-control: no-cache");
header ("Pragma: no-cache");
header ("Expires: 0");

1
bu tüm sayfaya uygulanacak .... Önbelleği yalnızca bir resim için devre dışı bırakamıyorum (o sayfadaki belirli bir resim)?
dole doug

5
@Thorpe: HTTP yanıtları için geçerlidir. Yanıtın içerdiği şey ilgisizdir. Görüntü verileri, HTML verileri veya başka herhangi bir şey olsun. Eğer işe yaramadıysa, muhtemelen doğru yapmadınız. Doğru şekilde atanıp atanmadıklarını görmek için yanıtınızdaki HTTP üstbilgilerini kontrol edin.
lhunath

Bunun işe yaramasını diliyorum ... Chrome'da herhangi bir sorun yok, ancak Firefox 14 ve IE 8, yukarıdaki başlıklar gönderilse bile görüntüleri yenilemeyi reddediyor. Bu, sorgu dizesine bazı rastgele parametreler eklemekten çok daha temiz bir çözüm olurdu. sigh
Pawel Krakowiak

2
@PawelKrakowiak Tarayıcı, sunucuya onlar hakkında soru sormadığından ve bu nedenle başlıkları asla görmeyeceğinden, üstbilgi eklemenin zaten önbelleğe alınmış görüntüler için işe yaramayacağını unutmayın . Siz ekledikten sonra yapılan tüm resim istekleri için çalışacaklar.
lhunath

2
Bu çözüm, web tasarımcıları için değil programcılar için tasarlanmıştır. Buna işaret edeceğimi düşündüm, çünkü bir görüntüyü kendileri bir programlama dilinde oluşturmadıkça, bir görüntüyü açıp görüntüleyip başlıklar ekleyemezsiniz ve bu yorum yapanlar kafa karıştırıcı gibi görünüyor.
Bruce

13

JavaScript kullanarak tarayıcıda dinamik olarak yapmanız gerekiyorsa, işte bir örnek ...

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

12

Çözüm 1 harika değil. İşe yarıyor, ancak görüntü dosyalarınızın sonuna rasgele veya zaman damgalı sorgu dizeleri eklemek, tarayıcının, bir sayfa her yüklendiğinde, görüntünün değişip değişmediğine bakılmaksızın her görüntünün her sürümünü yeniden indirmesini ve önbelleğe almasını sağlar. sunucuda.

Çözüm 2 işe yaramaz. Ekleme nocachebir resim dosyasına başlıkları uygulamak sadece çok zor değil, ama gerektirir çünkü tamamen pratik olduğunu önceden gerekli olacak zaman tahmin , ilk kez düşündüğünüzden herhangi resim yüklemek kudreti gelecekte bir noktada değişikliği .

Etags girin ...

Bunu çözmek için bulduğum en iyi yol , ETAGS'ı resimler dizininizdeki bir .htaccess dosyası içinde kullanmaktır. Aşağıdakiler Apache'ye, görüntü dosyası başlıklarında tarayıcıya benzersiz bir karma göndermesini söyler. Bu karma yalnızca, görüntü dosyası değiştirildiğinde her zaman değişir ve bu değişiklik, tarayıcının görüntüyü bir sonraki istendiğinde yeniden yüklemesini tetikler.

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

11

Tüm cevapları kontrol ettim ve en iyisi göründü (ki değil):

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

Başta.

Ancak, cache = none parametresini (statik "yok" kelimesi olan) eklerseniz , hiçbir şeyi etkilemez, tarayıcı yine de önbellekten yükler.

Bu sorunun çözümü şuydu:

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

Parametreyi dinamik yapmak ve önbellek olmadan temelde unix zaman damgası eklediğiniz yerde işe yaradı.

Ancak benim sorunum biraz farklıydı: Anında oluşturulmuş php grafik görüntüsünü yüklüyordum ve sayfayı $ _GET parametreleriyle kontrol ediyordum. URL GET parametresi aynı kaldığında görüntünün önbellekten okunmasını ve GET parametreleri değiştiğinde önbelleğe alınmamasını istedim.

Bu sorunu çözmek için $ _GET hash'lamam gerekiyordu ama dizi olduğu için çözüm burada:

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

Düzenle :

Yukarıdaki çözüm gayet iyi çalışsa da, bazen dosya değişene KADAR önbelleğe alınmış sürümü sunmak istersiniz. (yukarıdaki çözümle, bu görüntünün önbelleğini tamamen devre dışı bırakır) Dolayısıyla, tarayıcıdan önbelleğe alınmış görüntüyü sunmak için görüntü dosyası kullanımında bir değişiklik OLANA KADAR:

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

filemtime () dosya değiştirme zamanını alır.


4

Bu konunun eski olduğunu biliyorum ama Google'da çok iyi sıralanıyor. Bunu başlığınıza koymanın iyi çalıştığını öğrendim;

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

Modern tarayıcı maalesef bu yönergeleri görmezden geliyor, bu nedenle bu çözüm yalnızca bazı tarayıcılarda çalışabilir, ayrıca her şey için önbelleği devre dışı bırakır, yalnızca belirli görüntüler için değil
ZioCain

4

Ben sadece buna bir çözüm arıyordum ve yukarıdaki cevaplar benim durumumda işe yaramadı (ve onlar hakkında yorum yapmak için yeterli itibarım yok). Görünüşe göre, en azından benim kullanım durumum ve kullandığım tarayıcı (OSX'te Chrome) için, önbelleğe almayı engelleyen tek şey şuydu:

Cache-Control = 'no-store'

Tamlık için şimdi 3 'önbelleksiz, depolamasız, yeniden doğrulamalı' 3'ün hepsini kullanıyorum

Bu yüzden benim durumumda (Python'da Flask'tan dinamik olarak oluşturulmuş görüntüler sunmak), umarım mümkün olduğunca çok tarayıcıda çalışmak için aşağıdakileri yapmak zorunda kaldım ...

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


Yalnızca Chrome'da değil, Firefox için de. Artık bir standart gibi görünüyor: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control (" Önbelleğe almayı önleme " bölümüne bakın).
Gino Mempin

3

Görüntü kaynağını değiştirmek çözümdür. Resme bir zaman damgası veya rastgele sayı ekleyerek bunu gerçekten yapabilirsiniz.

Örneğin görüntünün temsil ettiği verilerin bir sağlama toplamı eklemek daha iyidir. Bu, mümkün olduğunda önbelleğe almayı sağlar.


1

Demetlere başka bir çözüm ekleyelim.

Sonunda benzersiz bir dize eklemek mükemmel bir çözümdür.

example.jpg?646413154

Aşağıdaki çözüm, bu yöntemi genişletir ve hem önbelleğe alma yeteneği sağlar hem de görüntü güncellendiğinde yeni bir sürüm getirir.

Görüntü güncellendiğinde, dosya zamanı değişecektir.

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

Şimdi görüntüyü çıkarın:

<img src="images/example.jpg?<?php echo $filemtime; ?>" >

1
Önbelleğe alma geçerliliği nedeniyle kullandığım şey buydu.
gen

1

Bu sorunu yaşadım ve bu şekilde üstesinden geldim.

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

0

Bunu benzer problemimi çözmek için kullandım ... bir görüntü sayacı göstererek (harici bir sağlayıcıdan). Her zaman doğru şekilde yenilenmedi. Ve rastgele bir parametre eklendikten sonra her şey yolunda gidiyor :)

En az dakikada bir yenilemeyi sağlamak için bir tarih dizesi ekledim.

örnek kod (PHP):

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

Bu, aşağıdaki srcgibi bir bağlantıyla sonuçlanır :

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

0

Kodlanmış bir görüntü URL'niz varsa, örneğin: http://example.com/image.jpg görüntünüze başlık eklemek için php'yi kullanabilirsiniz.

Öncelikle apache'nin jpg'nizi php olarak işlemesi gerekir. Buraya bakın: PHP'yi file.php.jpg uzantısıyla çalıştırmak mümkün mü?

Görüntüyü (imagecreatefromjpeg) dosyadan yükleyin ve ardından önceki yanıtlardan başlıkları ekleyin. Başlıkları eklemek için php işlev başlığını kullanın.

Ardından görüntüyü imagejpeg işleviyle çıkarın.

Lütfen php'nin jpg resimlerini işlemesine izin vermenin çok güvensiz olduğuna dikkat edin. Ayrıca bu çözümü test etmediğimi de unutmayın, bu yüzden çalışmasını sağlamak size kalmış.


-1

Basit, bir başlık konumu gönderin.

Sitem, bir resim içeriyor ve resmi yükledikten sonra değişmiyor, sonra bu kodu ekliyorum:

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

Benim için çalışıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.