How to get the browser to cache images, with PHP?
If you are using php to check if the user is logged in before outputting the message, then you don't want the browser to cache the image.
The entire point of caching is to call the server once and then never call it again. If the browser caches the image, it won't call the server and your script won't run. Instead, the browser will pull your image from cache and display it, even if the user is no longer logged in. This could potentially be a very big security hole.
Caching images in browser with URL parameters and XSendFile
I think this is a duplicate.
But since there is a bounty lets try to adapt your code together with the suggested solution there.
You need to check that Apache has mod_expires and mod_headers enabled and working properly.
And then before you start real output check if file was modified:
...
$last_modified_time = filemtime($file);
$etag = md5_file($file);
// always send headers
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $last_modified_time)." GMT");
header("Etag: $etag");
// exit if not modified
if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time ||
@trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) {
header("HTTP/1.1 304 Not Modified");
exit;
} else {
header("X-Sendfile: $file");
header("Content-type: application/octet-stream");
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
}
Prevent browser from caching images
Try putting a random variable on the end of the url
http://www.test.com/images/123.jpg?{{rand()}}
Image generated with PHP caching
There are a few options, depending on your situation. If "images/image.png" is an actual file on the server and you are accessing it directly, then you have to change the cache settings on the folder or use .htaccess to inform a browser to resend it.
<FilesMatch "\.(ico¦pdf¦flv¦jpg¦jpeg¦png¦gif¦js¦css¦swf)$">
ExpiresDefault A604800
Header set cache-control: "no-cache, public, must-revalidate"
</FilesMatch>
If you are using PHP to find the image and returning it, you can use PHP to send headers.
header("Expires: ".gmdate("D, d M Y H:i:s", time()+1800)." GMT");
header("Cache-Control: max-age=1800");
To do it perfectly with PHP, you can check if its actually modified
$last_modified_time = @filemtime($file);
header("Expires: ".gmdate("D, d M Y H:i:s", $last_modified_time+1800)." GMT");
//change with $last_modified_time instead of time().
//Else if you request it 29mins after it was first created, you still have to wait 30mins
//but the image is recreated after 1 min.
header("Cache-Control: max-age=1800");
header("Vary: Accept-Encoding");
// exit if not modified
if (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) {
if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time) {
header("HTTP/1.1 304 Not Modified");
return;
}
}
Cache AND display images php
I think this is what you looking for:
<?php
if(empty($_GET['user_id']) || !preg_match( '/^[0-9]+$/' , $_GET['user_id'])){
header( '400 Bad Request' );
exit(1);
}
include_once "DBH.php";
$user_id = intval( $_GET['user_id'] );
$result = $conn->query("SELECT image FROM profilePictures WHERE user_id = $user_id");
if($result->num_rows == 0){
// Not Found
header('404 Not Found');
exit(1);
}
$imgData = $result->fetch_assoc();
header("Content-type: image");
$cache_for = 3600; // One hour in seconds
$cache_until = gmdate("D, d M Y H:i:s", time() + $cache_for) . " GMT";
header("Expires: $cache_until");
header("Pragma: cache");
header("Cache-Control: max-age=$cache_for");
echo $imgData['image'];
exit(0);
Comments
First I checked if the user_id
is supplied in the request, if so then check if it was a valid number if it doesn't then respond with a 400
error.
And also I have removed a SQLi in your code src='displayProfilePicture.php?user_id=-1 or 1=1
.
And I have set the caching headers, so the browser will cache the image for an hour.
How to prevent browser image caching?
Just put a random parameter at the end of the image URL. A timestamp can also be used very well for this.
For example in PHP:
"http://domain.com/img.png?t=" . time();
The browser will always load this image new. You should use it with care though, it will make loading times slower.
Browser Caching of images and videos served via php query strings
Thanks @tim!
The problem was in the headers i was serving alongside my media. I looked at the response in Chrome and it said:
Cache-Control: must-revalidate, no-cache, no-store
I didn't set these, it must be a default of apache since I'm serving through a script? Anyways, to fix, I just added:
Cache-Control: public
to my PHP file and it seems to be working!
How to browser cache image from php
You could modify your imgtag.php
file, so it sends that header, using the PHP header()
function :
header('Cache-Control: max-age=2592000');
Note : setting headers must be done before any output.
Do browsers cache images?
Yes the browser will cache them, often even when your headers say otherwise. I have found the best combination is to issue the necessary Cache-Control headers along with appending a random string to the source URL.
Example, set the max age in seconds:
header("Cache-Control: max-age=3600");
Then append a random string to your img sources. This will need to be in Javascript, not in PHP because once your URLs are generated in PHP they won't keep updating with a new random string:
var randomString = "" + new Date().getTime();
var imageUrl = yourImageArray[someIndex] + "?" + randomString;
Hope you get the idea.
Related Topics
How to Check If Curl Is Enabled or Disabled
Close Open HTML Tags in a String
Laravel Trailing Slashes Redirect to Localhost
Why Does Password_Verify Return False
How to Remove Square Brackets and Anything Between Them with a Regex
Force Browser to Download Image with JavaScript Window.Open
Warning: MySQLi_Error() Expects Exactly 1 Parameter, 0 Given Error
Using PHP Replace Spaces in Urls with %20
Call to Undefined Function _() Error - PHPmyadmin
How to Read "Fetch(Pdo::Fetch_Assoc);"
Using Simplexml to Read Rss Feed
Sharing Session Variables Between Multiple Subdomains
Resize Images in PHP Without Using Third-Party Libraries
How Does the "&" Operator Work in a PHP Function
Laravel Preg_Match(): No Ending Delimiter '/' Found