會員登入 新使用者?立即註冊

新網址 http://claire-chang.com/

關閉
你好,歡迎你來到小佳的程式天地! 我要留言

利用header做檔案下載控制

分類:PHP
2009/01/08 21:06

在許多線上電影或許多軟體下載的網站,
都可以看到一個連結讓你點此下載,而無法讓你直接利用網址連接至被下載的檔案
這可以防止外站直接將檔案下載的連結連到你的站。
增加自己網站的負荷量卻沒增加人氣。

要達到這樣的功能,有幾種方式:
1. 利用php來存取控管檔案,所有的下載皆經過php檔案去處理。
2. 將檔案以BLOB的方式存進資料庫,以資料庫方式下載吐出檔案。

但是將檔案存進資料庫的話,在修改檔案內容、存取檔案上都將會較為不便
較為簡單的方式,是利用header去做檔案控制與下載的動作,
相關的詳細介紹可見: http://tw.php.net/header

下面的函數可以讓下載的檔案經由php處理再交由使用者下載,
我們可以將檔案放在伺服器主機上無法直接經由http存取的位置,
再利用php程式去存取本機電腦檔案。

這樣使用者便無法直接由網址來存取下載的檔案。

function dl_file($file){

   //檢查檔案是否存在
   if (!is_file($file)) { die("404 File not found!"); }

   //取得檔案相關資料
   $len = filesize($file);
   $filename = basename($file);
   $file_extension = strtolower(substr(strrchr($filename,"."),1));

   //將檔案格式設定為將要下載的檔案
  switch( $file_extension ) {
     case "pdf": $ctype="application/pdf"; break;
     case "exe": $ctype="application/octet-stream"; break;
     case "zip": $ctype="application/zip"; break;
     case "doc": $ctype="application/msword"; break;
     case "xls": $ctype="application/vnd.ms-excel"; break;
     case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
     case "gif": $ctype="image/gif"; break;
     case "png": $ctype="image/png"; break;
     case "jpeg":
     case "jpg": $ctype="image/jpg"; break;
     case "mp3": $ctype="audio/mpeg"; break;
     case "wav": $ctype="audio/x-wav"; break;
     case "mpeg":
     case "mpg":
     case "mpe": $ctype="video/mpeg"; break;
     case "mov": $ctype="video/quicktime"; break;
     case "avi": $ctype="video/x-msvideo"; break;
     //禁止下面幾種類型的檔案被下載
     case "php":
     case "htm":
     case "html":
     case "txt": die("Cannot be used for ". $file_extension ." files!"); break;

     default: $ctype="application/force-download";
   }

   //開始編寫header
   header("Pragma: public");
   header("Expires: 0");
   header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
   header("Cache-Control: public");
   header("Content-Description: File Transfer");
  
   //使用利用 switch判別的檔案類型
   header("Content-Type: $ctype");

   //執行下載動作
   $header="Content-Disposition: attachment; filename=".$filename.";";
   header($header );
   header("Content-Transfer-Encoding: binary");
   header("Content-Length: ".$len);
   @readfile($file);
   exit;
}

若您只是單純的要下載某個檔案,不需要用到上面那麼複雜的php類別,
可以直接使用下面的程式碼去下載檔案

$saveasname = "test.csv"; //要被儲存成的檔名
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; Filename="'.$saveasname.'"');

上面的程式碼丟在 script 的前面送出 header 後
後面再將要存入的內容 echo 出來
瀏覽器自動會出現下載的功能...

如果想加快下載速度,可將Content-Encoding宣告為Gzip,
將檔案內容先壓縮過再提供給使用者下載,
這個非常適合用來做資料庫備份,
phpMyAdmin就是用這個方式來做資料庫備份的輸出輸入下載
檔案可以不用先存到伺服器端直接下載至客戶端,
增加執行的速度

//檔名
$saveasname = "test.txt.gz";
//Header設定
header('Content-Encoding:x-gzip');
header('Content-Type: application/x-gzip');
header('Content-Disposition: attachment; Filename="'.$saveasname.'"');
header('Pragma: no-cache');
//要輸出的內容用gzencode函式處理過
echo gzencode('hi', 9);

以下是關於GZIP的介紹
http://www.faqs.org/rfcs/rfc2616

上一篇 下一篇
回應(5)
大毛2010/07/02 23:45 回應

您好我想請教你因為我有一套免費線上檔案管理系統它的下載語語法

與上面的差不多 像我的系統會遇到中文檔名時下載系統會遇到下載檔案為亂碼

起初以為是MYsql 因為是非utf-8儲存 還特別改成utf-8(讓介面與資料顯示同步 而不是亂碼)

所以我想問妳你上面的語法下載時檔明會跑掉嗎?

另外像這樣 還有什麼建議修改方式嗎?

我的檔案管理系統是Mydms (1.7)  更新版是Letodms(1.81)

在後台實際儲存檔案的資料夾有目錄密碼 但是不影響使用 只是防止有心人 未經授權瀏覽

架在虛擬主機上系統:http://data1.nocsh1955.wiwi0204.twbbs.org/

謝謝 等待你傳來好消息了

orin2010/05/16 13:47 回應

可以轉載嗎 = =? 會標上作者的 : D

woff2010/04/22 19:44 回應

大大看不太懂第一段他怎麼執行呢?

請大大說明一下

MAXMAS2009/02/27 10:05 回應

嗯 .. 很不錯的實用技術
繼續加油...

pikaca.tw2009/01/11 18:38 回應

哇..

找了好久竟然被我找到這個網站

有好多關於各種程式語言的資料唷^^

對於正準備學習PHP的我是個好地方!!

謝謝版大把自己的用心和苦心發表在此

造福更多人群^^

引用(0)
雅虎資訊 版權所有 © 2013 Yahoo! Taiwan All Rights Reserved
「本服務設有管理員」 服務條款 隱私權政策