PHP - browser not caching dynamic image - php

I am having trouble getting my image script to cache the image in the browser (firefox).
Here is the code :
$type = 'image/jpeg';
$image = '../../files/image.jpeg';
header("Content-type: $type");
header("Cache-Control: private, max-age=10800, pre-check=10800");
header("Pragma: private");
header("Expires: " . date(DATE_RFC822,strtotime("1 week")));
if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])){
header('Last-Modified: '.$_SERVER['HTTP_IF_MODIFIED_SINCE'],true,304);
exit;
} else {
header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($image)).' GMT', true, 200);
echo #readfile($image);
exit;
}
The image gets outputted, however after that it always goes to the else statement with the 200 response code instead of the 304. I tried to force the 304, but it looks like the image is never cached by the browser.

Try to call it as jpg (add this in htaccess:
RewriteEngine on
RewriteRule image.jpg your_script.php [L]
)
don't forgot to change your_script.php and image.jpg

Related

PHP - Warning: getimagesize failed to open stream: HTTP request failed

I am getting this error:
Warning: getimagesize(http://dev.clearcaresolutions.local/viewimage.php?file=screenshot_from_2016-11-29_12-12-06.png&type=form):
failed to open stream: HTTP request failed! HTTP/1.0
500 Internal
Server Error in /var/www/vhosts/dev.clearcaresolutions.local/current/modules/tasks/edit_log.php on line 845
This is the response code (please don't judge, I didn't write this, I have to live with it :/ ):
$fSize = filesize($dataPath.'/'.$file);
$fType = cFile::getMimeType($file);
// write the HTML headers
header ("X-Frame-Options: sameorigin");
#header("X-Frame-Options: deny"); # on
header ("X-XSS-Protection: 1; mode=block"); # off
header ("X-Content-Type-Options: nosniff"); # on
// BEGIN extra headers to resolve IE caching bug (JRP 9 Feb 2003)
header("Pragma: "); # on
header("Cache-Control: "); # on
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); # on
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); # on
header("Cache-Control: no-store, no-cache, must-revalidate"); //HTTP/1.1 # on
header("Cache-Control: post-check=0, pre-check=0", false); # on
// END extra headers to resolve IE caching bug
header("MIME-Version: 1.0");
header("Content-Description: File Transfer");
header("Content-Length: {$fSize}"); # ---
header("Content-Type: {$fType}"); # on
header("Content-Transfer-Encoding: binary"); # ---
header("Content-disposition: {$mode}; filename={$file}"); # on
echo readfile($dataPath.'/'.$file);
$fSize and $fType are correct, so this is not the issue.
This is how I call the response:
$protocol = stripos($_SERVER['SERVER_PROTOCOL'],'https') === true ? 'https://' : 'http://';
(line 845) list($width, $height) = getimagesize($protocol.$_SERVER['SERVER_NAME'].$field['fieldsrc']);
When I use $field['fieldsrc'] (which looks something like this:
/viewimage.php?file=screenshot_from_2016-11-29_12-12-06.png&type=form
as a data for src inside image tag, the image is shown properly, so I am guessing the response is correct. Any idea what is wrong here?
readfile already outputs the content of the file. Remove the echo in front of it. It should be only
readfile($dataPath.'/'.$file);

Return Character (Newline) inserted at top of file which corrupts the file PHP?

I have a function that returns an image from a database, the image is 100% fine in the database however when it is sent to the browser a newline (return) character is inserted in the very beginning and it corrupts the file.
The code to return the file is:
//if(ob_get_length() > 0)
//{
//ob_clean();
//}
Commented the above out as when it is uncommented it doesn't even let the browser download the file.
function header_file($data, $file_data)
{
$last_modified = gmdate('D, d M Y H:i:s', $file_data['unix_last_modified_time'])." GMT";
// update the accessed record
$GLOBALS['db']->query("update file_uploads set file_upload_accessed_count = file_upload_accessed_count + 1 where file_upload_id = '".$GLOBALS['id']."'");
// if browser question if it's up to date
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
{
// parse header
$if_modified_since = preg_replace('/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE']);
if ($if_modified_since == $last_modified)
{
// the browser's cache is still up to date
header("HTTP/1.0 304 Not Modified");
header("Cache-Control: max-age=86400, must-revalidate");
exit;
}
}
header("Cache-Control: max-age=86400, must-revalidate");
header("Last-Modified: ".$last_modified);
header("Content-Type: ".$file_data['file_upload_type']);
if($file_data['file_upload_type'] == 'application/x-shockwave-flash')
header("Content-Disposition: inline; filename=\"".str_replace(' ','_',$file_data['file_upload_name'])."\"");
else
header("Content-Disposition: attachment; filename=\"".str_replace(' ','_',$file_data['file_upload_name'])."\"");
// send data to output
echo $data;
exit;
}
Related Questions:
Corrupted File from PHP Header File returned from database?
https://stackoverflow.com/questions/19768650/zend-caching-of-images-gives-problems-once-the-site-goes-down-for-a-while
I would do the following. You have an extra space somewhere in your PHP file.
It can be a bit tricky to find, so start putting some
echo "here"
in your code to see if this newline is found before or after the echo. Keep moving he echo statement up or down the file until you can see where it is (it might be in an include file, so you will have to track it down.
---------------START OF FILE

set-cookie header multiple times

I have this code in a assets controller to get images:
function images($path,$image_name)
{
$image = "../assets/images/$path/$image_name";
if (file_exists ($image) && (is_file($image))) {
$name = $image_name;
} else {
}
$file = getimagesize($image);
$filesize = filesize($image);
$time_cache = 360000000000;
$ts = gmdate("D, d M Y H:i:s", time() + $time_cache) . " GMT";
header("Content-Type: {$file['mime']}\n");
header("Content-disposition: inline; filename=\"$name\"\n");
header("Content-Length: $filesize\n");
header("Expires: $ts");
header("Pragma: cache");
header("Cache-Control: max-age=$time_cache");
readfile ($image);
}
I have set csrf protection to true in config/config.php file and every request for an image is sent with Set-Cookie header. So the csrf-cookie can get set multiple times on some pages. Is that something to worry about, and if so, is there a way to prevent this?
I managed to do this with header_remove("set-cookie");
So the code looks like this
header("Content-Type: {$file['mime']}\n");
header("Content-disposition: inline; filename=\"$name\"\n");
header("Content-Length: $filesize\n");
header("Expires: $ts");
header("Pragma: cache");
header("Cache-Control: max-age=$time_cache");
header_remove("set-cookie");
readfile ($image);
If in only one page/image request you uses setcookie function many times, php will send many times the same cookie to browser in one response. Maybe some browsers crashes reading that.
I've had problems with ajax requests in Internet Explorer due to multiple cookie definitions, when accidentally start the session object in CakePHP into a loop. I only detected that problem sniffing the connection with wireshark.

create javascript code in a php file - SAFARI/CHROME doesn't work

I've created a .php file that write out js code like that:
<?
//my_js.php
// javascript header
header('Content-type: text/javascript');
// Date in the past
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
// always modified
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
// HTTP/1.1
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
?>
//
// js code here
//
then i include the script above in my index.php file like this:
<script type="text/javascript" src="my_js.php?id=<? echo $id ?>">
</script>
This works perfect in Firefox, but SAFARI and CHROME doesn't include my_js.php file at all!
What i'm doing wrong?
**edit:
this is the rendered html in index.php:
<script type="text/javascript" src="my_js.php?id=new"></script>
and this is the my_js.php code:
(it's a very big file so i write out only the first few lines)
var g = { sitepath: "myNullUrl" }
function getBrowserWidth(){
if (window.innerWidth){
return window.innerWidth;}
else if (document.documentElement && document.documentElement.clientWidth != 0){
return document.documentElement.clientWidth; }
else if (document.body){return document.body.clientWidth;}
return 0;
}
that's a strange problem 'cos while i'm viewing source code from Crome/Safari i can access the js file and it seems to be error free!
I'm using Chrome 6.04 and Safari 5, both for mac.
It may be because it is expecting the file-extension to be my_js.js. If this is the case, save your PHP file as my_js.js, then, assuming you're using Apache, use the Apache Directive: ForceType:
Like so:
<Location /your/path/my_js.js>
ForceType application/x-httpd-php
</Location>
Good luck!
Maybe set Content-Disposition: inline; header?
<?php
if(strstr($_SERVER["HTTP_USER_AGENT"],"MSIE")==false) {
header("Content-type: text/javascript");
header("Content-Disposition: inline; filename=\"download.js\"");
header("Content-Length: ".filesize("my-file.js"));
} else {
header("Content-type: application/force-download");
header("Content-Disposition: attachment; filename=\"download.js\"");
header("Content-Length: ".filesize("my-file.js"));
}
header("Expires: Fri, 01 Jan 2010 05:00:00 GMT");
if(strstr($_SERVER["HTTP_USER_AGENT"],"MSIE")==false) {
header("Cache-Control: no-cache");
header("Pragma: no-cache");
}
include("my-file.js
");
?>
It should work. Or you can change this:
header('Content-type: text/javascript');
to this
header('Content-type: application/javascript');
Note:
application/javascript: JavaScript; Defined in RFC 4329 but not accepted in IE 8 or earlier
text/javascript is allowed in HTML 4 and 5 and, unlike application/javascript, has cross-browser support

Anyway to bring up the 'Open / Save' dialogue for the user?

Not sure if the title makes sense sorry... basically I'm generating Word documents that I wanted to open automatically on the client's machine, but it seems this isn't possible, so instead of just presenting a list and having them manually click on each one, I was wondering if at the very least it could bring up the 'Would you like to save or open this file' dialogue :(
Long shot, but I know a lot of sites will do this when you download stuff... re-directing to download server etc
Thanks
The best you can do is provide a "hint" with the Content-disposition header.
http://php.net/manual/en/function.header.php
Specifying something like
<?php
header('Content-type: application/msword');
header('Content-Disposition: attachment; filename="downloaded.pdf"');
// output content of document
?>
should cause most browsers to prompt the user to download the document, while this:
header('Content-Dispotion: inline')
should usually cause the browser to show the file in the existing window.
You can set the contenttype and content-disposition header to open the open/save dialog box in browser.
See
Header Field Definition
for details.
You need to send the correct header and so on.
I found this that seems good:
<?php
function send_file($name) {
ob_end_clean();
$path = "protected/".$name;
if (!is_file($path) or connection_status()!=0) return(FALSE);
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Expires: ".gmdate("D, d M Y H:i:s", mktime(date("H")+2, date("i"), date("s"), date("m"), date("d"), date("Y")))." GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Content-Type: application/octet-stream");
header("Content-Length: ".(string)(filesize($path)));
header("Content-Disposition: inline; filename=$name");
header("Content-Transfer-Encoding: binary\n");
if ($file = fopen($path, 'rb')) {
while(!feof($file) and (connection_status()==0)) {
print(fread($file, 1024*8));
flush();
}
fclose($file);
}
return((connection_status()==0) and !connection_aborted());
}
?>
And here's an example of using the function:
<?php
if (!send_file("platinumdemo.zip")) {
die ("file transfer failed");
// either the file transfer was incomplete
// or the file was not found
} else {
// the download was a success
// log, or do whatever else
}
?>

Categories