php實現文件下載功能總結
其實所謂的下載按鈕根本就是個A標簽,里面記錄着要下載文件的路徑,如果要下載的文件恰巧是圖片或者是文本文件,那么下載的時候就會被瀏覽器彈出一個新窗口或者直接頁面跳轉掉並且直接打開這個文件,解決方法是將下載的文件改成壓縮后的格式或者是瀏覽器不能直接打開的格式。
下面我來說一下下載的流程:瀏覽器發送一個請求,請求訪問服務器中的某個網頁(如:down.php),服務器接受到該請求以后,馬上運行該down.php文件,運行該文件的時候,必然要把將要被下載的文件讀入內存當中,這里通過fopen()函數完成該動作,現在文件已經在內存當中了,這是需要從內存當中讀取文件,通過fread()函數完成該動作需要注意的是,如果文件較大,文件應該是被分成多段返回給客戶端的,並不是等文件在服務端全部讀取完畢后,一次性返回給客戶端,因為這樣子會增加服務器的負荷。所以我們需要php代碼中設置一次讀取的字節數,比如我在下面的代碼中通過$buffer=1024設置一次讀取的字節數,每讀取一次,就輸出數據。
header("Content-type:text/html;charset=utf-8")的作用:在服務器響應瀏覽器的請求時,告訴瀏覽器以編碼格式為UTF-8的編碼顯示該內容,關於file_exists()函數不支持中文路徑的問題:因為php函數比較早,不支持中文,所以如果被下載的文件名是中文的話,需要對其進行字符編碼轉換,否則file_exists()函數不能識別,可以使用iconv()函數進行編碼轉換。$file_sub_path() 我使用的是絕對路徑,執行效率要比相對路徑高,Header("Content-type: application/octet-stream")的作用:通過這句代碼客戶端瀏覽器就能知道服務端返回的文件形式。Header("Accept-Ranges: bytes")的作用:告訴客戶端瀏覽器返回的文件大小是按照字節進行計算的。Header("Accept-Length:".$file_size)的作用:告訴瀏覽器返回的文件大小。Header("Content-Disposition: attachment; filename=".$file_name)的作用:告訴瀏覽器返回的文件的名稱。fclose($fp)可以把緩沖區內最后剩余的數據輸出到磁盤文件中,並釋放文件指針和有關的緩沖區。這些就是下載時候的整個流程和必要的代碼。下面附上整理的下載方法,已封裝好,可直接使用:
代碼如下:
1 <?php 2 //文件下載,下載一張圖片 3 //$file_name="Angel.mp3"; 4 $file_name="bjnihao.jpg"; //出現中文 程序無法完成下載 提示:文件不存在 5 //對文件進行轉碼(PHP文件函數 比較古老 需對中文碼轉成 gb2312) 6 //iconv — Convert string to requested character encoding 7 //by www.jb51.net 8 $file_name=iconv("utf-8","gb2312",$file_name); 9 //設置文件下載路徑(相對路徑) 10 //$file_path="./dowm/".$file_name; 11 //使用絕對路徑 12 $file_path=$_SERVER['DOCUMENT_ROOT']."/http/dowm/".$file_name; 13 //打開文件---先判斷再操作 14 if(!file_exists($file_path)){ 15 16 echo "文件不存在"; 17 return ; //直接退出 18 } 19 //存在--打開文件 20 $fp=fopen($file_path,"r"); 21 22 //獲取文件大小 23 $file_size=filesize($file_path); 24 //http 下載需要的響應頭 25 header("Content-type: application/octet-stream"); //返回的文件 26 header("Accept-Ranges: bytes"); //按照字節大小返回 27 header("Accept-Length: $file_size"); //返回文件大小 28 header("Content-Disposition: attachment; filename=".$file_name);//這里客戶端的彈出對話框,對應的文件名 29 //向客戶端返回數據 30 //設置大小輸出 31 $buffer=1024; 32 //為了下載安全,我們最好做一個文件字節讀取計數器 33 $file_count=0; 34 //判斷文件指針是否到了文件結束的位置(讀取文件是否結束) 35 while(!feof($fp) && ($file_size-$file_count)>0){ 36 $file_data=fread($fp,$buffer); 37 //統計讀取多少個字節數 38 $file_count+=$buffer; 39 //把部分數據返回給瀏覽器 40 echo $file_data; 41 } 42 //關閉文件 43 fclose($fp); 44 ?>
封裝函數:
1 <?php 2 /* 3 封裝函數: 4 參數說明----$file_name:文件名 5 $file_sub_dir:文件下載的子路徑 6 */ 7 function file_dowm($file_name,$file_sub_dir){ 8 //文件轉碼 9 $file_name=iconv("utf-8","gb2312",$file_name); 10 //使用絕對路徑 11 $file_path=$_SERVER['DOCUMENT_ROOT']."$file_sub_dir".$file_name; 12 //打開文件---先判斷再操作 13 if(!file_exists($file_path)){ 14 15 echo "文件不存在"; 16 return ; //直接退出 17 } 18 //存在--打開文件 19 $fp=fopen($file_path,"r"); 20 21 //獲取文件大小 22 $file_size=filesize($file_path); 23 /* 24 //這里可以設置超過多大不能下載 25 if($file_size>50){ 26 echo "文件太大不能下載"; 27 return ; 28 }*/ 29 //http 下載需要的響應頭 30 header("Content-type: application/octet-stream"); //返回的文件 31 header("Accept-Ranges: bytes"); //按照字節大小返回 32 header("Accept-Length: $file_size"); //返回文件大小 33 header("Content-Disposition: attachment; filename=".$file_name);//這里客戶端的彈出對話框,對應的文件名 34 //向客戶端返回數據 35 //設置大小輸出 36 $buffer=1024; 37 //為了下載安全,我們最好做一個文件字節讀取計數器 38 $file_count=0; 39 //判斷文件指針是否到了文件結束的位置(讀取文件是否結束) 40 while(!feof($fp) && ($file_size-$file_count)>0){ 41 $file_data=fread($fp,$buffer); 42 //統計讀取多少個字節數 43 $file_count+=$buffer; 44 //把部分數據返回給瀏覽器 45 echo $file_data; 46 } 47 //關閉文件 48 fclose($fp); 49 } 50 51 file_dowm("bjnihao.jpg","/http/dowm/"); 52 ?>
另一個代碼:
1 public function downloads($name){ 2 $name_tmp = explode("_",$name); 3 $type = $name_tmp[0]; 4 $file_time = explode(".",$name_tmp[3]); 5 $file_time = $file_time[0]; 6 $file_date = date("Y/md",$file_time); 7 $file_dir = SITE_PATH."/data/uploads/$type/$file_date/"; 8 9 if (!file_exists($file_dir.$name)){ 10 header("Content-type: text/html; charset=utf-8"); 11 echo "File not found!"; 12 exit; 13 } else { 14 $file = fopen($file_dir.$name,"r"); 15 Header("Content-type: application/octet-stream"); 16 Header("Accept-Ranges: bytes"); 17 Header("Accept-Length: ".filesize($file_dir . $name)); 18 Header("Content-Disposition: attachment; filename=".$name); 19 echo fread($file, filesize($file_dir.$name)); 20 fclose($file); 21 } 22 }
文件下載 出現下載文件內容亂碼損壞的解決方法:
1 ob_clean(); 2 flush();