php 实现下载
实现文件下载的基本方法
在PHP中实现文件下载可以通过设置HTTP头部信息并输出文件内容来完成。以下是基本实现方式:
$file_path = '/path/to/your/file.pdf';
$file_name = 'download.pdf';
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($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);
强制下载而非打开
确保浏览器总是弹出下载对话框而非尝试打开文件:
header('Content-Type: application/force-download');
header('Content-Disposition: attachment; filename="'.basename($file_name).'"');
安全注意事项
验证文件路径防止目录遍历攻击:

$base_dir = '/safe/download/directory/';
$file_path = realpath($base_dir . $_GET['file']);
if (strpos($file_path, $base_dir) !== 0) {
die('Invalid file path');
}
显示下载进度
对于需要显示下载进度的情况,可以计算并输出进度信息:
$total_size = filesize($file_path);
$downloaded = 0;
while (!feof($handle)) {
$buffer = fread($handle, $chunk_size);
$downloaded += strlen($buffer);
$progress = round(($downloaded / $total_size) * 100);
echo $buffer;
// 可以在这里记录或输出进度信息
ob_flush();
flush();
}
断点续传支持
实现支持断点续传的下载:
$range = isset($_SERVER['HTTP_RANGE']) ? $_SERVER['HTTP_RANGE'] : false;
if ($range) {
list($param, $range) = explode('=', $range);
if (strtolower(trim($param)) != 'bytes') {
header('HTTP/1.1 400 Invalid Request');
exit;
}
$range = explode('-', $range);
$start = intval($range[0]);
$end = isset($range[1]) ? intval($range[1]) : $total_size - 1;
header('HTTP/1.1 206 Partial Content');
header("Content-Range: bytes $start-$end/$total_size");
header("Content-Length: " . ($end - $start + 1));
fseek($handle, $start);
} else {
header("Content-Length: $total_size");
}






