php 实现文件下载
实现文件下载的基本方法
使用 PHP 实现文件下载的核心是通过设置 HTTP 头部信息,强制浏览器将文件作为附件下载而非直接显示。以下是一个基础实现示例:
$file_path = '/path/to/your/file.pdf';
$file_name = 'download.pdf';
if (file_exists($file_path)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $file_name . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file_path));
readfile($file_path);
exit;
}
处理大文件下载
对于大文件下载,可以使用分块读取方式避免内存问题:
$file_path = '/path/to/large_file.zip';
$chunk_size = 1024 * 1024; // 1MB chunks
$handle = fopen($file_path, 'rb');
while (!feof($handle)) {
echo fread($handle, $chunk_size);
ob_flush();
flush();
}
fclose($handle);
安全下载控制
确保下载文件的安全性,防止目录遍历攻击:
$base_dir = '/secure/downloads/';
$requested_file = $_GET['file'];
$real_path = realpath($base_dir . $requested_file);
// 验证文件是否在允许的目录内
if ($real_path && strpos($real_path, realpath($base_dir)) === 0 && is_file($real_path)) {
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($real_path) . '"');
readfile($real_path);
} else {
header('HTTP/1.0 404 Not Found');
echo 'File not found';
}
断点续传支持
实现支持断点续传的文件下载:
$file_path = '/path/to/resumable.file';
$file_size = filesize($file_path);
$range = isset($_SERVER['HTTP_RANGE']) ? $_SERVER['HTTP_RANGE'] : null;
if ($range) {
list($unit, $range) = explode('=', $range, 2);
if ($unit == 'bytes') {
list($start, $end) = explode('-', $range, 2);
$start = (int)$start;
$end = $end ? (int)$end : $file_size - 1;
header('HTTP/1.1 206 Partial Content');
header('Content-Range: bytes ' . $start . '-' . $end . '/' . $file_size);
header('Content-Length: ' . ($end - $start + 1));
}
} else {
header('Content-Length: ' . $file_size);
}
$handle = fopen($file_path, 'rb');
if ($range) {
fseek($handle, $start);
$remaining = $end - $start + 1;
while ($remaining > 0) {
echo fread($handle, min(8192, $remaining));
$remaining -= 8192;
flush();
}
} else {
while (!feof($handle)) {
echo fread($handle, 8192);
flush();
}
}
fclose($handle);
下载进度显示
使用输出缓冲和 JavaScript 实现前端进度显示:
// PHP 部分
$file_path = '/path/to/file';
$file_size = filesize($file_path);
$chunk_size = 1024 * 1024; // 1MB
header('Content-Length: ' . $file_size);
// 其他必要的头部信息
$handle = fopen($file_path, 'rb');
while (!feof($handle)) {
echo fread($handle, $chunk_size);
ob_flush();
flush();
// 可以在这里计算并输出进度信息
}
fclose($handle);
// 前端 JavaScript 部分
// 使用 XMLHttpRequest 或 Fetch API 监控下载进度
这些方法涵盖了从基础到高级的文件下载实现,可以根据具体需求选择适合的方案。







