首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 實現檔案下載的兩種核心方法完整解析

     編輯:PHP 相關知識

在 PHP 開發中,實現檔案下載功能是常見需求。本文詳細解析兩種主流實現方式,並說明關鍵 Header 設定與注意事項,幫助開發者選擇適合專案的方案。

方法一:標準 Header 串流下載(適用於大檔案)

此方法透過設定完整的 HTTP Header,瀏覽器會彈出「另存新檔」對話框,適合任意類型檔案,且支援斷點續傳與大檔案傳輸。

<?php
$filepath = '/path/to/your/file.zip'; // 檔案實際路徑
$filename = basename($filepath);       // 取得檔案名稱

// 1. 宣告輸出為二進位串流
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');

// 2. 指定下載檔名,防止中文檔名亂碼建議使用 urlencode
header('Content-Disposition: attachment; filename="' . urlencode($filename) . '"');
header('Content-Transfer-Encoding: binary');

// 3. 快取控制:強制瀏覽器不快取,確保每次都是最新內容
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');

// 4. 告知瀏覽器檔案大小,支援進度條顯示
header('Content-Length: ' . filesize($filepath));

// 5. 直接輸出檔案內容到輸出緩衝區
readfile($filepath);
exit(); // 確保腳本結束,避免輸出多餘內容
?>

關鍵點說明:

  • Content-Type: application/octet-stream:通用二進位類型,瀏覽器不會嘗試直接開啟。
  • Content-Disposition: attachment:強制下載而非在瀏覽器開啟。
  • Content-Length:提供檔案大小,讓瀏覽器顯示下載進度。
  • readfile():高效讀取檔案並直接輸出,不佔用 PHP 記憶體,適合大檔案。

方法二:簡易 MIME 類型對應下載(快速實作)

此方法根據副檔名動態設定 MIME 類型,程式碼較精簡,適合已知檔案類型的情境。

<?php
$filename = '/path/to/document.pdf';
$fileinfo = pathinfo($filename);

// 根據副檔名設定 MIME 類型(實際專案建議使用 mime_content_type() 或 finfo)
$mimeTypes = [
    'pdf' => 'application/pdf',
    'jpg' => 'image/jpeg',
    'png' => 'image/png',
    'zip' => 'application/zip',
    // ... 可自行擴充
];
$ext = strtolower($fileinfo['extension']);
$mime = $mimeTypes[$ext] ?? 'application/octet-stream';

header('Content-type: ' . $mime);
header('Content-Disposition: attachment; filename="' . urlencode($fileinfo['basename']) . '"');
header('Content-Length: ' . filesize($filename));
readfile($filename);
exit();
?>

優缺點比較:

特性方法一方法二
通用性極高,不依賴副檔名需維護 MIME 對照表
中文檔名支援需自行 urlencode同上
大檔案效能優(readfile 串流)優(同用 readfile)
程式碼複雜度稍多精簡

進階建議與安全提醒

  1. 路徑驗證:絕對不可直接使用使用者輸入的路徑,必須經過 realpath() 驗證並在允許目錄內,防止目錄遍歷攻擊。
  2. 中文檔名處理:建議統一使用 urlencode() 編碼檔名,並在前端以 decodeURIComponent() 解碼,相容性最佳。
  3. 記憶體限制:大檔案下載時,確保 memory_limit 設定合理,readfile() 不會將檔案載入記憶體,但輸出緩衝區仍需注意。
  4. 斷點續傳支援:若需支援 HTTP Range 請求,需自行解析 $_SERVER['HTTP_RANGE'] 並發送 206 Partial Content,可參考 RFC 7233。

綜上所述,方法一 因其通用性與標準合規性,建議作為專案預設下載實作;方法二 適合快速原型或檔案類型固定的內部系統。實際部署時,請務必加入權限檢查與路徑清理,確保資料安全。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved