php怎么实现下载文件
实现文件下载的基本方法
使用PHP的header()函数设置HTTP头信息,配合readfile()函数实现文件下载。确保在输出文件内容前没有其他输出,避免头信息发送失败。
$file_path = '/path/to/your/file.pdf';
$file_name = 'custom_name.pdf';
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;
处理大文件下载
对于大文件下载,使用分块读取方式避免内存耗尽问题。
$chunk_size = 1024 * 1024; // 1MB chunks
$handle = fopen($file_path, 'rb');
while (!feof($handle)) {
echo fread($handle, $chunk_size);
ob_flush();
flush();
}
fclose($handle);
安全验证
添加权限验证和路径安全检查,防止目录遍历攻击。
if (!user_has_permission()) {
die('Access denied');
}
$base_dir = '/secure/downloads/';
$real_path = realpath($base_dir . $requested_file);
if (strpos($real_path, $base_dir) !== 0) {
die('Invalid file path');
}
断点续传支持
实现HTTP Range请求处理,支持断点续传功能。
$file_size = filesize($file_path);
if (isset($_SERVER['HTTP_RANGE'])) {
$range = $_SERVER['HTTP_RANGE'];
$range = str_replace('bytes=', '', $range);
list($start, $end) = explode('-', $range);
header('HTTP/1.1 206 Partial Content');
header("Content-Range: bytes $start-$end/$file_size");
header("Content-Length: " . ($end - $start + 1));
$fp = fopen($file_path, 'rb');
fseek($fp, $start);
echo fread($fp, ($end - $start + 1));
fclose($fp);
}
下载统计功能
记录下载日志到数据库,用于统计分析。
$stmt = $pdo->prepare("INSERT INTO download_logs
(file_id, user_id, download_time)
VALUES (?, ?, NOW())");
$stmt->execute([$file_id, $user_id]);






