眾所周知php對http協議的依賴特別強,像java或者asp.net在某些情況下可以不依賴http例如asp.net的winform,對php來說文件下載可以使用http的請求頭加上php的IO就可以實現了
1.先來看下下載所要用的的請求頭
header("Content-type:application/octet-stream"); header("Accept-Ranges:bytes"); header("Accept-Length:".$file_Size); header("Content-Disposition: attachment; filename=".$filename);
content-type就不解釋了,Accept-Ranges表示接收數據的類型或者范圍,圖片屬於二進制的東西所以需要使用字節的方式傳輸,Accept-Lenght表示接收的大小,php文件下載需要告訴瀏覽器下載的文件有多大,最后一個是附件只需要把文件名給過去就可以,這個名稱就是下載時顯示的文件名稱。
2.php的文件操作出現的比較早,文件名是中文的時候需要注意轉碼
$filename=iconv("UTF-8","GB2312",$filename);
3.php的文件下載機制是首先apcahe把文件信息讀入服務器內存,然后使用請求頭把文件二進制信息通過瀏覽器傳給客戶端
//判斷路徑是否存在 if(!file_exists($filepath)){ echo "文件不存在"; return; } $fp=fopen($filepath,"r"); //取得文件大小 $file_Size=filesize($filepath); header("Content-type:application/octet-stream"); header("Accept-Ranges:bytes"); header("Accept-Length:".$file_Size); header("Content-Disposition: attachment; filename=".$filename); $buffer=1024; $buffer_count=0; while(!feof($fp)&&$file_Size-$buffer_count>0){ $data=fread($fp,$buffer); $buffer_count+=$buffer; echo $data; } fclose($fp);
feof用來判斷文件是否已經讀到了末尾,fread用來把文件讀入緩沖區,緩沖區的大小是1024,一邊讀取一邊把數據輸出到瀏覽器。為了下載的安全性每次讀數據都進行字節的計數。文件讀取完畢后關閉輸入流
3.上面的代碼有的時候不好使,可以清空(擦掉)輸出緩沖區,使用下面的代碼即可
ob_clean();
來看下運行效果圖
下載之后文件也沒有任何的問題
下面是全部代碼
<?php function downloadFile($name){ ob_clean(); $filename=$name; $filename=iconv("UTF-8","GB2312",$filename); $filepath="E:\\otherphp\\download\\download\\".$filename; //判斷路徑是否存在 if(!file_exists($filepath)){ echo "文件不存在"; return; } $fp=fopen($filepath,"r"); //取得文件大小 $file_Size=filesize($filepath); header("Content-type:application/octet-stream"); header("Accept-Ranges:bytes"); header("Accept-Length:".$file_Size); header("Content-Disposition: attachment; filename=".$filename); $buffer=1024; $buffer_count=0; while(!feof($fp)&&$file_Size-$buffer_count>0){ $data=fread($fp,$buffer); $buffer_count+=$buffer; echo $data; } fclose($fp); } downloadFile("桌面截圖.png"); ?>