很多場景需要「點擊下載、頁面不跳轉、不彈新窗」。本文提供一套基於隱藏 <iframe> 的輕量方案,兼容性極佳,代碼量極小,適合快速集成到現有專案。
display:none 的 <iframe>srcContent-Disposition: attachment 的響應public function downFile($path = '') {
if (!$path) header("Location: /");
download($path); // 調用下載核心函數
}
function download($file_url, $new_name = '') {
if (!isset($file_url) || trim($file_url) === '') { echo '500'; return; }
if (!file_exists($file_url)) { echo '404'; return; }
$file_name = basename($file_url);
$ext = pathinfo($file_url, PATHINFO_EXTENSION);
$file_name = $new_name ? urlencode($new_name) : $file_name;
$fp = fopen($file_url, 'rb');
// 輸出下載頭
header("Content-Type: application/octet-stream");
header("Accept-Ranges: bytes");
header("Content-Length: " . filesize($file_url));
header("Content-Disposition: attachment; filename=\"{$file_name}\"");
// 分塊輸出,防大文件佔記憶體
while (!feof($fp)) {
echo fread($fp, 8192);
ob_flush(); flush();
}
fclose($fp);
exit;
}
<iframe id="downFrame" src="" style="display:none;"></iframe>
<a href="javascript:;" class="downLoad" path="/data/report.pdf">下載報告</a>
<a href="javascript:;" class="downLoad" path="/data/image.png">下載圖片</a>
<script>
$(function(){
$('.downLoad').click(function(){
var path = $(this).attr('path');
$('#downFrame').attr('src', "/controller/downFile?path=" + encodeURIComponent(path));
});
});
</script>
| 問題 | 解決方案 |
|---|---|
| 中文文件名亂碼 | 使用 urlencode() 編碼,配合 filename*=UTF-8'' 標準寫法 |
| 大文件記憶體溢出 | 採用 fread 分塊讀取 + ob_flush/flush 即時輸出 |
| 並發下載限制 | nginx/apache 配置 limit_rate_after、limit_rate 控制帶寬 |
| 權限控管 | 下載前驗證用戶身份、文件所有權、下載次數/頻率 |
若專案需求僅為「靜默下載」,iframe 方案是性價比最高的選擇。如需進度條、斷點續傳,請轉向 Blob/AJAX 或 WebUploader 等成熟組件。