PHP - 下載文件
你好,有抱負的PHP開發者們!今天,我們將要深入一個令人興奮的主題,讓你能在你的網站中加入一些很酷的功能 - 使用PHP下載文件。作為你們友善的鄰居電腦老師,我將在這次旅程中一步步地指導你們。所以,拿起你們最喜歡的飲料,放鬆身心,讓我們開始編程吧!
readfile()
函數
在PHP中實現文件下載的核心是 readfile()
函數。這個小巧的函數是你的首选工具,當你需要讀取文件並將其內容寫入輸出緩衝區時。現在,別擔心這聽起來有點專業 - 我們會一起剖析它!
基本使用
讓我們從一個簡單的例子開始:
<?php
readfile("example.txt");
?>
在這段代碼中,readfile()
讀取 "example.txt" 的內容並直接輸出到瀏覽器。這就像魔法一樣 - 文件的內容會出現在屏幕上!
下載文件
現在我们來看看更有趣的部分。我們可以使用 readfile()
來提示文件下載。讓我們看一個更完整的例子:
<?php
$file = "myfile.pdf";
if(file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
?>
哇,這有很多要吸收的!讓我們分解一下:
- 我們指定我們想要下載的文件 (
$file = "myfile.pdf"
)。 - 我們使用
file_exists()
來檢查文件是否存在。 - 如果存在,我們設置一系列的頭部信息:
-
Content-Description
告訴瀏覽器這是一個文件傳輸。 -
Content-Type
設置MIME類型為通用二進制文件。 -
Content-Disposition
導致瀏覽器下載文件。 - 其他頭部信息確保文件不被緩存並被正確對待。
- 最後,我們使用
readfile()
來輸出文件內容。
常見文件類型
不同的文件類型可能需要不同的頭部信息。這裡有一個常用文件類型和對應的 Content-Type
頭部信息的便捷表格:
文件類型 |
Content-Type 頭部信息 |
---|---|
application/pdf | |
ZIP | application/zip |
JPEG | image/jpeg |
PNG | image/png |
MP3 | audio/mpeg |
MP4 | video/mp4 |
創建下載鏈接
現在我們知道如何觸發下載,讓我們創建一個用戶友好的下載鏈接:
<!DOCTYPE html>
<html>
<body>
<h2>下載文件</h2>
<p><a href="download.php?file=myfile.pdf">下載 PDF</a></p>
</body>
</html>
在這個HTML中,我們創建一個鏈接指向一個PHP腳本 (download.php
) 來處理文件下載。我們在URL中傳遞文件名作為參數。
現在,讓我們創建 download.php
腳本:
<?php
if(isset($_GET['file'])) {
$file = $_GET['file'];
$filepath = "uploads/" . $file;
if(file_exists($filepath)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($filepath).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filepath));
readfile($filepath);
exit;
} else {
echo "文件未找到。";
}
}
?>
這個腳本會執行以下操作:
- 檢查URL中是否有文件參數。
- 構建完整的文件路徑(假設文件在 "uploads" 目錄中)。
- 如果文件存在,它設置頭部信息並觸發下載。
- 如果文件不存在,它顯示一個錯誤消息。
安全考慮
現在我知道你在想什麼 - "但是老師,這不是有點風險嗎?如果有人試圖下載他們不應該下載的文件怎麼辦?" 好問題!你完全正確,這就是我們需要談論安全性的原因。
驗證文件路徑
我們絕對不應該直接信任用戶輸入。這裡是我們下載腳本的改進版本:
<?php
if(isset($_GET['file'])) {
$file = basename($_GET['file']);
$filepath = "uploads/" . $file;
// 驗證文件路徑
$realPath = realpath($filepath);
$uploadDir = realpath("uploads/");
if($realPath === false || strpos($realPath, $uploadDir) !== 0) {
die("無效的文件路徑。");
}
if(file_exists($filepath)) {
// ...(下載代碼的其余部分)
} else {
echo "文件未找到。";
}
}
?>
在這個版本中:
- 我們使用
basename()
來刪除任何目錄遍歷嘗試。 - 我們使用
realpath()
來獲得文件的實際路徑和上傳目錄的路徑。 - 我們檢查文件的實際路徑是否以上傳目錄路徑開始,確保我們不會訪問到指定目錄之外的文件。
結論
好了,各位!我們已經穿越了PHP文件下載的領地,從 readfile()
的基礎知識到創建下載鏈接,甚至觸及了一些重要的安全考慮。記住,能力越大,責任越大 - 當你處理文件下載時,總是要驗證用戶輸入並考慮安全性。
我希望你們喜歡這個課程,就像我喜歡教這個課程一樣。持續練習,持續編程,在你們知道之前,你們將會創建有各種酷炫下載功能的PHP應用程序。下次見,快樂編程!
Credits: Image by storyset