php下载进度实现
PHP 下载进度实现
在 PHP 中实现下载进度显示通常需要结合前端和后端技术,以下是一种常见的实现方法:
使用 PHP 的 readfile() 或 fread() 结合 JavaScript
这种方法通过分块读取文件并输出到浏览器,同时在前端通过 AJAX 或 EventSource 获取进度信息。
// download.php
$file_path = '/path/to/large/file.zip';
$file_size = filesize($file_path);
$chunk_size = 1024 * 1024; // 1MB chunks
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file_path).'"');
header('Content-Length: '.$file_size);
$handle = fopen($file_path, 'rb');
while (!feof($handle)) {
echo fread($handle, $chunk_size);
ob_flush();
flush();
// 可以在这里记录进度到 session 或文件
$_SESSION['download_progress'] = ftell($handle) / $file_size * 100;
}
fclose($handle);
前端进度显示
<!-- progress.html -->
<div id="progress">0%</div>
<script>
function checkProgress() {
fetch('progress.php')
.then(response => response.json())
.then(data => {
document.getElementById('progress').innerText = data.progress + '%';
if (data.progress < 100) {
setTimeout(checkProgress, 500);
}
});
}
// 开始下载时调用
checkProgress();
window.location.href = 'download.php';
</script>
进度跟踪脚本
// progress.php
session_start();
header('Content-Type: application/json');
echo json_encode([
'progress' => $_SESSION['download_progress'] ?? 0
]);
使用 PHP 的 flush() 和 JavaScript 事件
这种方法不需要额外的 AJAX 请求,但需要浏览器支持 Server-Sent Events:
// sse_download.php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$file_path = '/path/to/file';
$file_size = filesize($file_path);
$downloaded = 0;
$handle = fopen($file_path, 'rb');
while (!feof($handle)) {
$chunk = fread($handle, 1024 * 1024);
$downloaded += strlen($chunk);
$percent = round(($downloaded / $file_size) * 100);
echo "data: {\"progress\": $percent}\n\n";
ob_flush();
flush();
usleep(100000); // 稍微延迟以显示进度
}
fclose($handle);
注意事项
- 确保服务器配置允许长时间运行的脚本
- 大文件下载可能需要调整 PHP 的 memory_limit 和 max_execution_time
- 进度信息存储可以使用 session、文件或数据库
- 对于更复杂的实现,可以考虑使用 WebSocket 替代 AJAX 轮询
以上方法可以根据具体需求进行调整和组合,以实现最佳的下载进度显示效果。







