Nonaktifkan cache untuk beberapa gambar

113

Saya menghasilkan beberapa gambar menggunakan PHP lib.

Terkadang browser tidak memuat file yang baru dibuat.

Bagaimana cara menonaktifkan cache hanya untuk gambar yang saya buat secara dinamis?

Catatan: Saya harus menggunakan nama yang sama untuk gambar yang dibuat dari waktu ke waktu.

dole doug
sumber

Jawaban:

233

Solusi umum dan sederhana untuk masalah ini yang terasa seperti retasan tetapi cukup portabel adalah dengan menambahkan string kueri yang dibuat secara acak ke setiap permintaan untuk gambar dinamis.

Jadi, misalnya -

<img src="image.png" />

Akan menjadi

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

Atau

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

Dari sudut pandang server web, file yang sama diakses, tetapi dari sudut pandang browser tidak ada cache yang dapat dilakukan.

Pembuatan nomor acak dapat terjadi baik di server saat menyajikan halaman (cukup pastikan halaman itu sendiri tidak di-cache ...), atau di klien (menggunakan JavaScript).

Anda perlu memverifikasi apakah server web Anda dapat mengatasi trik ini.

Segi enam
sumber
87
Sebagai ganti nomor acak, gunakan stempel waktu saat data berubah atau nomor versi dari data yang direfleksikan.
lhunath
19
Harap diperhatikan: Anda tidak benar-benar mencegah browser untuk menyimpan gambar, Anda hanya mencegah melihat gambar yang di-cache. Menerapkan header yang tepat ke gambar Anda adalah cara terbaik (lihat solusi lhunath di bawah). Karena cara ini Anda juga mengisi cache secara tidak perlu dengan gambar yang tidak ingin Anda cache dengan biaya menyebabkan lebih sedikit ruang cache untuk hal-hal yang sebenarnya ingin Anda cache.
Jos
Saya yakin artikel ini menjelaskan alasan perilaku tersebut.
Metalcoder
1
ini tidak benar-benar berfungsi, gambar perlu dibilas dengan cara lain (biasanya pada pemotongan gambar, gambar tetap sama)
Ben
44

Strategi cache browser dapat dikontrol oleh header HTTP. Ingatlah bahwa itu hanyalah petunjuk, sungguh. Karena browser sangat tidak konsisten dalam bidang ini (dan lainnya), Anda memerlukan beberapa header untuk mendapatkan efek yang diinginkan pada berbagai browser.

header ("Pragma-directive: no-cache");
header ("Cache-directive: no-cache");
header ("Cache-control: no-cache");
header ("Pragma: no-cache");
header ("Expires: 0");
lhunath
sumber
1
ini akan ditampilkan ke seluruh halaman .... Saya tidak dapat menonaktifkan cache untuk satu gambar saja (gambar tertentu dari halaman itu)?
dole doug
5
@Thorpe: Ini berlaku untuk tanggapan HTTP. Apa yang terkandung dalam tanggapan tidak relevan. Baik itu data gambar, data HTML atau apapun. Jika tidak berhasil, Anda mungkin tidak melakukannya dengan benar. Periksa header HTTP pada respons Anda untuk melihat apakah sudah ditetapkan dengan benar.
lhunath
Saya berharap ini berhasil ... Chrome tidak memiliki masalah, tetapi Firefox 14 dan IE 8 menolak untuk menyegarkan gambar bahkan dengan tajuk di atas sedang dikirim. Ini akan menjadi solusi yang jauh lebih bersih daripada menambahkan beberapa parameter arbitrer ke string kueri. menghela napas
Pawel Krakowiak
2
@PawelKrakowiak Perhatikan bahwa menambahkan header tidak akan bekerja untuk gambar yang sudah di-cache , karena browser bahkan tidak menanyakan server tentang mereka dan oleh karena itu tidak akan pernah melihat header. Mereka akan berfungsi untuk permintaan gambar apa pun yang dibuat setelah Anda menambahkannya.
lhunath
2
Solusi ini ditujukan untuk programmer, bukan desainer web. Saya pikir saya akan menunjukkannya karena seseorang tidak bisa begitu saja membuka dan menggambar dan menambahkan header ke gambar, kecuali mereka sendiri yang membuat gambar dalam bahasa pemrograman dan ini tampaknya membingungkan pemberi komentar.
Bruce
13

Jika Anda perlu melakukannya secara dinamis di browser menggunakan javascript, berikut adalah contohnya ...

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

Solusi 1 tidak bagus.Itu berfungsi, tetapi menambahkan string kueri hacky random atau timestamped ke akhir file gambar Anda akan membuat browser mengunduh ulang dan menyimpan cache setiap versi dari setiap gambar, setiap kali halaman dimuat, terlepas dari cuaca gambar berubah atau tidak di server.

Solusi 2 tidak berguna. Menambahkan nocacheheader ke file gambar tidak hanya sangat sulit untuk diterapkan, tetapi juga sangat tidak praktis karena mengharuskan Anda untuk memprediksi kapan itu akan dibutuhkan sebelumnya , pertama kali Anda memuat gambar yang menurut Anda mungkin berubah di beberapa titik di masa mendatang. .

Masukkan Etags ...

Cara terbaik mutlak yang saya temukan untuk memecahkan masalah ini adalah dengan menggunakan ETAGS di dalam .htaccess file di direktori gambar Anda. Perintah berikut memberi tahu Apache untuk mengirim hash unik ke browser di header file gambar. Hash ini hanya akan berubah ketika file gambar diubah dan perubahan ini memicu browser untuk memuat ulang gambar saat diminta lagi.

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

Saya memeriksa semua jawaban dan yang terbaik sepertinya (yang tidak):

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

pertama.

Namun, jika Anda menambahkan cache = none parameter (yang merupakan kata "tidak ada" statis), itu tidak berpengaruh apa-apa, browser masih memuat dari cache.

Solusi untuk masalah ini adalah:

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

di mana Anda pada dasarnya menambahkan stempel waktu unix untuk membuat parameter dinamis dan tidak ada cache, itu berhasil.

Namun, masalah saya sedikit berbeda: Saya memuat gambar bagan php dengan cepat, dan mengontrol halaman dengan parameter $ _GET. Saya ingin gambar dibaca dari cache ketika parameter URL GET tetap sama, dan tidak melakukan cache ketika parameter GET berubah.

Untuk mengatasi masalah ini, saya perlu hash $ _GET tetapi karena itu adalah array, inilah solusinya:

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

Edit :

Meskipun solusi di atas berfungsi dengan baik, terkadang Anda ingin menyajikan versi yang di-cache SAMPAI file diubah. (dengan solusi di atas, itu menonaktifkan cache untuk gambar itu sepenuhnya) Jadi, untuk menyajikan gambar yang di-cache dari browser HINGGA ada perubahan dalam penggunaan file gambar:

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

filemtime () mendapat waktu modifikasi file.

Tarik
sumber
4

Saya tahu topik ini sudah lama, tetapi peringkatnya sangat baik di Google. Saya menemukan bahwa meletakkan ini di header Anda bekerja dengan baik;

<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
sumber
Browser modern sayangnya mengabaikan arahan ini, oleh karena itu solusi ini mungkin hanya berfungsi pada beberapa browser, juga, itu akan menonaktifkan cache untuk semuanya, tidak hanya gambar tertentu
ZioCain
4

Saya hanya mencari solusi untuk ini, dan jawaban di atas tidak berhasil dalam kasus saya (dan saya memiliki reputasi yang tidak memadai untuk mengomentarinya). Ternyata, setidaknya untuk kasus penggunaan saya dan browser yang saya gunakan (Chrome di OSX), satu-satunya hal yang tampaknya mencegah caching adalah:

Cache-Control = 'no-store'

Untuk kelengkapan, saya sekarang menggunakan semua 3 dari 'no-cache, no-store, must-revalidate'

Jadi dalam kasus saya (menyajikan gambar yang dihasilkan secara dinamis dari Flask dengan Python), saya harus melakukan hal berikut agar dapat bekerja di sebanyak mungkin browser ...

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
Menandai
sumber
Hanya memberi tanggapan tanpa toko sudah cukup untuk membuatnya bekerja untuk saya
scourge192
Tidak hanya di Chrome, juga untuk Firefox. Tampaknya menjadi standar sekarang: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control (lihat bagian " Mencegah cache ").
Gino Mempin
3

Mengubah sumber gambar adalah solusinya. Anda memang dapat melakukan ini dengan menambahkan stempel waktu atau nomor acak ke gambar.

Lebih baik menambahkan checksum misalnya data yang diwakili oleh gambar. Ini memungkinkan penyimpanan dalam cache jika memungkinkan.

Stefan van Gastel
sumber
1

Mari tambahkan solusi lain satu ke kelompok itu.

Menambahkan string unik di akhir adalah solusi yang tepat.

example.jpg?646413154

Solusi berikut memperluas metode ini dan menyediakan kemampuan caching dan mengambil versi baru ketika gambar diperbarui.

Ketika gambar diperbarui, filemtime akan berubah.

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

Sekarang keluaran gambar:

<img src="images/example.jpg?<?php echo $filemtime; ?>" >
Daniel
sumber
1
Itulah yang saya gunakan karena validitas caching.
gen
1

saya punya masalah ini dan mengatasi seperti ini.

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

Saya telah menggunakan ini untuk menyelesaikan masalah serupa saya ... menampilkan penghitung gambar (dari penyedia eksternal). Itu tidak selalu menyegarkan dengan benar. Dan setelah parameter acak ditambahkan, semuanya berfungsi dengan baik :)

Saya telah menambahkan string tanggal untuk memastikan penyegaran setidaknya setiap menit.

kode contoh (PHP):

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

Itu menghasilkan srctautan seperti:

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

Jika Anda memiliki URL gambar hardcode, misalnya: http://example.com/image.jpg Anda dapat menggunakan php untuk menambahkan header ke gambar Anda.

Pertama, Anda harus membuat proses apache jpg Anda sebagai php. Lihat di sini: Apakah mungkin untuk mengeksekusi PHP dengan ekstensi file.php.jpg?

Muat gambar (imagecreatefromjpeg) dari file lalu tambahkan header dari jawaban sebelumnya. Gunakan header fungsi php untuk menambahkan header.

Kemudian keluarkan gambar dengan fungsi imagejpeg.

Harap perhatikan bahwa sangat tidak aman membiarkan php memproses gambar jpg. Perlu diketahui juga bahwa saya belum menguji solusi ini jadi terserah Anda untuk membuatnya berfungsi.

Sam Sam
sumber
-1

Sederhana, kirim satu lokasi tajuk.

Situs saya berisi satu gambar, dan setelah upload gambar tersebut tidak ada perubahan, kemudian saya tambahkan kode ini:

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

Bekerja untukku.

Programador
sumber