常用http头

404
header('HTTP/1.1 404 Not Found');

301,302
#firefox中有时会缓存301跳转所以加上了缓存过期
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")."GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
header('HTTP/1.1 301 Moved Permanently');
header('Location: '.$url,true,301);

附件下载
header("Cache-Control: must-revalidate,post-check=0,pre-check=0");
header("Content-Description: File Transfer");
header ("Content-type: application/octet-stream");
header ("Content-Length: " .filesize ($f_name));
header ("Content-Disposition: attachment; filename=" . basename($f_name));
readfile($f_name);

PHPExcel下载
$filename='联盟排行榜'.$date.'.xlsx';
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header('Content-Disposition:inline;filename="'.$filename.'"');
header("Content-Transfer-Encoding: binary");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Pragma: no-cache");
$objWriter->save('php://output');

Excel
header('Content-Type: application/vnd.ms-excel');
header("Content-Disposition:attachment; filename=demo.xls");
header('Cache-Control: max-age=0');

通过http头设置http缓存

通过nginx可以设置http缓存

location ~* \.(js|css|gif|jpeg|jpg|png|ico|bmp)$ {
 expires 7d;
 access_log off;
 break;
}

用Chrome浏览器测试确实有缓存了,但是F5刷新接收到304之后还是会下载内容(和Ctrl+F5不同,Ctrl+F5会强制清除缓存并获取新内容,因为F5会发送If-Modified-Since和Ctrl+F5不会发送),用火狐浏览器测试接收到304之后并不下载实际文件内容(firebug时间线里面接收数据的部分所用时间是零),看样是浏览器之间的差异了。另外这样配置nginx的话在Chrome中图片缓存还是有问题,就下面这个截图我重新上传了之后(图片url和之前的图片一样)只有通过Ctrl+F5才会更新,Chrome对待js和img的方式不同。

通过PHP产生的JS也可以缓存

$content="var url={ base:'{$url['base']}',css:'{$url['css']}',js:'{$url['js']}',img:'{$url['img']}',image:'{$url['image']}',current:window.location};";
$expire=604800;
header('Content-type: application/x-javascript');
header('Cache-Control: max-age='.$expire);//1 month
//$now=gmmktime();
//header('Last-Modified: '.gmdate('D, d M Y H:i:s',$now-$expire).' GMT');
//header('Expires: '.gmdate('D, d M Y H:i:s', $now+$expire).' GMT');
header('Accept-Ranges: bytes');
header('Content-Length: '.strlen($content));
echo $content;

Accept-Ranges 和 Content-Length 也需要加上,头信息中如果不存在Content-Length 服务器端就会发送Tansfer-Encoding:chunked ,这个头信息的的意思是response的内容会被分成一块一块的发送,客户端不会等到内容都传输完毕了才解析其中的内容。如果指定了Content-Length 客户端会在接受完Content-Length长度的数据之后开始解析,这样就可以被缓存。

RFC上说Last-Modified和Expires 在这里被Cache-Control覆盖掉了,因为没仔细研究HTTP协议所以先放这。具体见撰写本文时的最新RFC2616直接搜索 Page 126 就看到了。