PHP下載文件的方式

PHP下載文件的方式

1. 獲得文件路徑

$_GET['file']獲得文件路徑php

$path_parts = pathinfo($_GET['file']);
$file_name  = $path_parts['basename'];
$file_path  = '/mysecretpath/' . $file_name;

務必使用上面這種方法獲得路徑,不能簡單的字符串拼接獲得路徑
$mypath = '/mysecretpath/' . $_GET['file'];
若是輸入的是../../,就能夠訪問任何路徑數組

2. 設置header信息

header('Content-Description: File Transfer'); //描述頁面返回的結果
header('Content-Type: application/octet-stream'); //返回內容的類型,此處只知道是二進制流。具體返回類型可參考http://tool.oschina.net/commons
header('Content-Disposition: attachment; filename='.basename($file));//可讓瀏覽器彈出下載窗口
header('Content-Transfer-Encoding: binary');//內容編碼方式,直接二進制,不要gzip壓縮
header('Expires: 0');//過時時間
header('Cache-Control: must-revalidate');//緩存策略,強制頁面不緩存,做用與no-cache相同,但更嚴格,強制意味更明顯
header('Pragma: public');
header('Content-Length: ' . filesize($file));//文件大小,在文件超過2G的時候,filesize()返回的結果可能不正確

3. 輸出文件之file_get_contents()方法

file_get_contents()把文件內容讀取到字符串,也就是要把文件讀到內存中,再輸出內容瀏覽器

$str = file_get_contents($file);
echo $str;

這種方式,只要文件稍微一大,就會超過內存限制緩存

4. 輸出文件之file()方法

file_get_contents()差很少,只不過是file()會把內容按行讀取到數組中,也是須要佔用內存app

$f = file($file);
while(list($line, $cnt) = each($f)) {
   echo $cnt;
}

文件大的時候也會超出內存限制ide

5. 輸出文件之readfile()方法

readfile()方法:讀入一個文件並寫入到輸出緩衝
這種方式能夠直接輸出到緩衝,不會整個文件佔用內存
前提要先清空緩衝,先要讓用戶看到下載文件的對話框編碼

while (ob_get_level()) ob_end_clean();
//設置完header之後
ob_clean();
flush();  //清空緩衝區
readfile($file);

這種方法能夠輸出大文件,讀取單個文件不會超出內存限制,但下面的狀況除外。
readfile()在多人讀取文件的時候一樣會形成PHP內存耗盡:http://stackoverflow.com/questions/6627952/why-does-readfile-exhaust-php-memoryidea

PHP has to read the file and it writes to the output buffer. So, for 300Mb file, no matter what the implementation you wrote (by many small segments, or by 1 big chunk) PHP has to read through 300Mb of file eventually..net

If multiple user has to download the file, there will be a problem. (In one server, hosting providers will limit memory given to each hosting user. With such limited memory, using buffer is not going to be a good idea. )
I think using the direct link to download a file is a much better approach for big files.code

大意:PHP須要讀文件,再輸出到緩衝。對於一個300M的文件,PHP最終仍是要讀300M內存。所以在多個用戶同時下載的時候,緩衝也會耗盡內存。(不對還請指正)

例如100個用戶在下載,就須要100*buffer_size大小的內存

6. 輸出文件之fopen()方法

set_time_limit(0);
$file = @fopen($file_path,"rb");
while(!feof($file))
{
    print(@fread($file, 1024*8));
    ob_flush();
    flush();
}

fopen()能夠讀入大文件,每次能夠指定讀取一部分的內容。在操做大文件的時候也頗有用

7. 總結

利用PHP下載文件時,應該要注重場景。若是自己只是幾個小文件被下載,那麼使用PHP下載比較好;可是若是PHP要承受大量下載請求,這時下載文件就不應交給PHP作。

對於Apache,有mod_xsendfile能夠幫助完成下載任務,更簡單也更快速

相關文章
相關標籤/搜索