Setting up Expire Headers with PHP - php

could anyone help me with setting up Expire Headers using PHP only,
.htaccess is no good, because my host won't enable mod_expires on apache.
So basically I'm looking for a way to do:
Expire Header
<FilesMatch "\.(ico|jpg|jpeg|png|gif|js|css|swf)$">
ExpiresDefault "access plus 365 days"
</FilesMatch>
with php only.
its also important to have different expire periods for different filetypes, so I tried using something like:
header ("content-type: image/jpg; charset: UTF-8");
header ("cache-control: must-revalidate");
$offset = 48 * 60 * 60;
$expire = "expires: " . gmdate ("D, d M Y H:i:s", time() + $offset) . " GMT";
header ($expire);
for each type of files, but nothing happened.
the headers after adding the PHP code, and taken from private session:
Response Headersview source
Date Mon, 25 Apr 2011 19:47:10 GMT
Server Apache/2.2.14 (Unix) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1
X-Powered-By PHP/5.3.1
P3P CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
Expires Mon, 1 Jan 2001 00:00:00 GMT
Cache-Control no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Last-Modified Mon, 25 Apr 2011 19:47:10 GMT
Content-Encoding gzip
Pragma no-cache
Keep-Alive timeout=5, max=100
Connection Keep-Alive
Transfer-Encoding chunked
Content-Type text/html; charset=utf-8
Request Headersview source
Host localhost
User-Agent Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.16) Gecko/20110323 Ubuntu/10.10 (maverick) Firefox/3.6.16 ( .NET CLR 3.5.30729) FirePHP/0.5
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language en-us,en;q=0.7,he;q=0.3
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 115
Connection keep-alive
Referer http://localhost/-----------------
Cookie fboard_settings[current_view]=flat; style_cookie=null; phpbb3_4s1go_k=; phpbb3_4s1go_u=2; phpbb3_4s1go_sid=8a3835a63834e9851b0cde3e2f6cff63; jw_clean_pro_tpl=jw_clean_pro; acpSearchCookie[searchphrase]=any; acpSearchCookie[acpSearch]=%D7%97%D7%A4%D7%A9+...; acpSearchCookie[cid]=0; acpSearchCookie[field_city]=0; 14a2bb08766d6180968b7925b7902d70=bgd3h1uj5dctoevtdiaj1jtmg6; 3e2fd857422e2463a01f9631f718017a=nbdjbmjsn9ee8ng90ui816hec2
x-insight activate

According to your comment in the question it looks like your system is running with a PHP setting of session.cache_limiter = nocache. This would automatically send the following headers:
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Only the Expires header you mention differs a bit (afaik Joomla uses that very datetime, if i'm not mistaken). But all in all it makes no difference, because both dates are in the past.
You should try with session_cache_limiter(false); in your code, to stop PHP sending its default caching headers:
function sendHeader($sType, $iLastModified, $iSecondsToCache)
{
$aType = array(
'ico' => 'image/x-icon',
'jpg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
'js' => 'text/javascript',
'css' => 'text/css',
'swf' => 'application/x-shockwave-flash'
);
if (!isset($aType[$sType]))
die('No mime type found for ' . $sType);
//$sLastModified = gmdate('r', $iLastModified);
$sLastModified = gmdate('D, d M Y H:i:s', $iLastModified) . ' GMT';
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
{
if ($_SERVER['HTTP_IF_MODIFIED_SINCE'] == $sLastModified)
{
header('HTTP/1.1 304 Not Modified');
exit;
}
}
session_cache_limiter(false);
//header('Expires: ' . gmdate('r', $iLastModified + $iSecondsToCache));
header('Expires: ' . gmdate('D, d M Y H:i:s', $iLastModified + $iSecondsToCache) . ' GMT');
header('Cache-Control: public');
header('Last-Modified: ' . $sLastModified);
header('Content-Type: ' . $aType[$sType]);
}
date_default_timezone_set('Europe/Berlin');
$iLastModified = strtotime('2011-04-25 07:08:09');
$iSecondsToCache = 48 * 60 * 60;
sendHeader('jpg', $iLastModified, $iSecondsToCache);
// stream sample image/jpeg content
$rGD = imagecreatetruecolor(100, 20);
$iColor = imagecolorallocate($rGD, 255, 255, 255);
imagestring($rGD, 1, 5, 5, 'Image to be cached', $iColor);
imagejpeg($rGD);
imagedestroy($rGD);
exit;
EDIT:
Meanwhile it's more probable to me, that Joomla is causing the problem. If the test code has access to Joomla libraries, try inserting:
jimport('joomla.environment.response');
JResponse::allowCache(true);
at the very top of the function and replace each header instruction with JResponse::setHeader.

That helps me for ajax queries:
header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s',time()+60*60*8 ) . ' GMT' );
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
header( 'Cache-Control: post-check=0, pre-check=0', false );
header( 'Pragma: no-cache' );

Related

PHP echos file as text instead of binary on server

I have written a PHP page which reads a file and does echo it after adding some headers:
header('Content-disposition: filename="' . $fname . '"');
header('Pragma: no-cache');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header("Content-type: $AttachFileType");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($ffullname));
echo file_get_contents($ffullname);
This piece of code does well on local test, but when porting to the server, the response is not as expected. For example when I want to retrieve a png file, I get the below image on local test:
while server test outputs this one:
As I have investigated, the only difference of them is 4 additional headers on server response. Local test response headers:
Cache-Control: must-revalidate, post-check=0, pre-check=0
Connection: Keep-Alive
Content-disposition: filename="attachment_hrmstotal_generalskills_6.png"
Content-Length: 2401
Content-Transfer-Encoding: binary
Content-Type: png
Date: Wed, 23 May 2018 04:45:02 GMT
Expires: 0
Keep-Alive: timeout=5, max=97
Pragma: public
Server: Apache/2.4.27 (Ubuntu)
and server response headers are these:
Cache-Control: must-revalidate, post-check=0, pre-check=0
Connection: keep-alive
Content-disposition: filename="attachment_hrmstotal_generalskills_1.png"
Content-Length: 184450
Content-Transfer-Encoding: binary
Content-Type: png
Date: Wed, 23 May 2018 04:40:56 GMT
Expires: 0
Pragma: public
Server: nginx/1.8.0
Strict-Transport-Security: max-age=31536000
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
The last four headers is the difference. What is the problem, its reason and how to solve it?
Your content-type should be Content-type: image/png

Resource interpreted as Document but transferred with MIME type application/csv

I have a button that downloads a CSV file.
The file seems to download fine but, I get the following warning.
This warning seems to only appear in chrome.
Resource interpreted as Document but transferred with MIME type application/csv:
This is where I set the CSV header.
/**
* Set the PHP mime header
*
* This will overwrite any previous headers
*
* #param string $header any custom headers that need to be set
*
* #return void
* #access public
*/
function setHeader($header='')
{
if ($header) {
// set custom headers
header($header);
} else {
header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename="'.$this->_filename.'";');
//This is known that Internet Explorer has problems with SSL connection (https).
//http://support.microsoft.com/default.aspx?scid=kb;en-us;812935
//http://support.microsoft.com/default.aspx?scid=kb;en-us;316431
// do not send no cache header in https for IE
// get protocol information
$url_info = parse_url(current_url());
$protocol = (isset($url_info['scheme'])) ? $url_info['scheme'] : NULL;
$using_ie6_8 = isset ($_SERVER['HTTP_USER_AGENT']) ? preg_match('/(MSIE\s[0-8]+\.)/', $_SERVER['HTTP_USER_AGENT']) : FALSE;
if (!is_null($protocol) && $protocol == 'https' && $using_ie6_8) {
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: private');
header('Expires: '.gmdate('D, d M Y H:i:s', time()-3600).' GMT');
}
}
}//end setHeader()
response header
Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection:keep-alive
Content-Disposition:attachment; filename="submission_log.csv";
Content-Type:application/csv
Date:Thu, 22 Sep 2016 04:59:06 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Pragma:no-cache
Server:openresty
Transfer-Encoding:chunked
X-Content-Type-Options:nosniff
X-Frame-Options:SAMEORIGIN
request header
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:6252
Content-Type:multipart/form-data; boundary=----WebKitFormBoundary4CxCF8KLzdtoGRO2
Cookie:lastSelectedLinkId=2661; lastSelectedAssetId=2151; SQ_SYSTEM_SESSION=o44hori3h2fcu5ltm29u6rv2k44bq1tu6v3364pdi8jn273scebnjm3lsuik5teasneeh664j98o3ajbur6p39kque68qgjohkktsk3; _ga=GA1.2.545099348.1472451817
Host:matrixdev.squiz.net
Origin:http://matrixdev.squiz.net
Referer:http://matrixdev.squiz.net/_admin/?SQ_BACKEND_PAGE=main&backend_section=am&am_section=edit_asset&assetid=2151&sq_asset_path=70%2C2151&sq_link_path=71%2C2661&asset_ei_screen=log
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36
if you have link inside <a> to download csv file, add "download" attribute to <a>.

Can not change cache control

I want to enable cache control for my page with this code :
<?php
$expires = 60 * 60 * 24 * 14;
header("Pragma: public");
header("Cache-Control: maxage=" . $expires);
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expires) . ' GMT');
?>
<!DOCTYPE html>
<html lang="en">...
I have added that at very begging of the page, but it does not work and I get this response :
Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection:Keep-Alive
Content-Encoding:gzip
Content-Length:40256
Content-Type:text/html
Date:Fri, 28 Mar 2014 18:57:59 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Keep-Alive:timeout=5, max=100
Pragma:no-cache
Server:Apache/2.4.6 (Ubuntu)
Vary:Accept-Encoding
X-Powered-By:PHP/5.5.7-1+sury.org~precise+1
Where is the problem ?

Content-length is capped to 2 GB

I've created a script that lets the user download files:
function file_size($filename)
{
exec('stat -c %s ' . escapeshellarg($filename), $return);
return (float)$return[0];
}
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($filename));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . file_size($filename));
readfile($filename);
exit;
Very simple. The file_size function lets me detect file sizes larger than 2 GB.
The problem is that Content-length never is above 2 GB:
< HTTP/1.1 200 OK
< Date: Sun, 21 Aug 2011 09:33:20 GMT
< Server: Apache
< Content-Description: File Transfer
< Content-Disposition: attachment; filename=very-large-file
< Content-Transfer-Encoding: binary
< Expires: 0
< Cache-Control: must-revalidate, post-check=0, pre-check=0
< Pragma: public
< Content-Length: 2147483647
< Content-Type: application/octet-stream
Doing a var_dump on 'Content-Length: ' . file_size($filename) returns string(26) "Content-Length: 4689218232". If I access the file directly without a PHP script, there is no problem and Apache is reporting the correct file size:
< HTTP/1.1 200 OK
< Date: Sun, 21 Aug 2011 09:58:33 GMT
< Server: Apache
< Last-Modified: Thu, 06 Jan 2011 21:56:47 GMT
< ETag: "8ba8f5e0-1177fcab8-49934940b30e5"
< Accept-Ranges: bytes
< Content-Length: 4689218232
But I'd really like to serve the file through my PHP script. Thank you for your time.
Sending huge files with readfile is not good practice.
Use X-Sendfile, like this: header("X-Sendfile: $filename");. You'll need apache mod_sendfile. This should also solve your file-size problem.

Changing CRC of a file through readfile()

I have this code set up that lets a user download a file through my server from a URL they specify. The file streams through using readfile() so it only uses my bandwidth.
<?php
set_time_limit(0);
$urlParts = explode("/", $_SERVER['PHP_SELF']);
$file = $urlParts[3];
header("Cache-Control: public, must-revalidate");
header("Pragma: hack");
header("Content-Type: application/force-download");
header('Content-Disposition: attachment; filename=' . $file);
header("Content-Transfer-Encoding: binary\n");
readfile($file);
?>
This script works, but it does not change the CRC hash of the downloaded file. What I want it to do is append some random bits to the end of the file so it can change the hash without corrupting it. I have tried adding something like echo md5(rand() . time()); to the end of the script but it doesn't work.
If this is possible with something like cURL I'd appreciate if someone could put up some code samples, because i'd switch to cURL if this was possible.
Thanks for your help.
Hmm, your code works for me:
test.php:
set_time_limit(0);
$urlParts = explode("/", $_SERVER['PHP_SELF']);
//$file = $urlParts[3];
$file = 'toread.txt';
header("Cache-Control: public, must-revalidate");
header("Pragma: hack");
header("Content-Type: application/force-download");
header('Content-Disposition: attachment; filename=' . $file);
header("Content-Transfer-Encoding: binary\n");
readfile($file);
echo md5(rand() . time());
?>
toread.txt:
This is the content of toread.txt
Now using curl, I get the following results:
>curl -i http://example.com/test.php
HTTP/1.1 200 OK
Date: Tue, 04 Mar 2014 07:09:39 GMT
Server: Apache
Cache-Control: public, must-revalidate
Pragma: hack
Content-Disposition: attachment; filename=toread.txt
Content-Transfer-Encoding: binary
Transfer-Encoding: chunked
Content-Type: application/force-download
Proxy-Connection: Keep-Alive
Connection: Keep-Alive
Age: 0
This is the content of toread.txt38d8a8009fad7315bdf5e823a06018e7
And the second one:
>curl -i http://example.com/test.php
HTTP/1.1 200 OK
Date: Tue, 04 Mar 2014 07:09:57 GMT
Server: Apache
Cache-Control: public, must-revalidate
Pragma: hack
Content-Disposition: attachment; filename=toread.txt
Content-Transfer-Encoding: binary
Transfer-Encoding: chunked
Content-Type: application/force-download
Proxy-Connection: Keep-Alive
Connection: Keep-Alive
Age: 0
This is the content of toread.txt3b87356ea9ee007b70cfd619e31da950

Categories