使用 readfile() - 推荐(最常用、最安全)
这是最推荐的方法,因为它最安全,并且性能最好,它不会将整个文件内容读入服务器的内存,而是直接以流的方式将文件发送给客户端,这对于大文件尤其重要。

工作原理
- 设置必要的 HTTP 头信息,告诉浏览器这是一个文件下载,而不是一个网页。
- 使用
readfile()函数,打开文件并将其内容直接输出到输出缓冲区。
代码示例 (download.php)
<?php
// 1. 指定要下载的文件路径
// !!! 重要: 请务必使用绝对路径,并且路径要安全 !!!
$file = '/var/www/html/uploads/my_document.pdf';
// 2. 检查文件是否存在
if (!file_exists($file)) {
die('文件不存在!');
}
// 3. 获取文件名(用于下载提示)
$filename = basename($file);
// 4. 设置 HTTP 头信息
// Content-Disposition: attachment; filename="..." 表示这是一个附件,浏览器会弹出下载框
// filename*=utf-8''... 用于处理非英文字符文件名,确保兼容性
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $filename . '"; filename*=utf-8\'' . $filename);
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
// 5. 清空并关闭输出缓冲区,确保没有多余内容输出
ob_clean();
flush();
// 6. 将文件内容读取并输出到浏览器
readfile($file);
// 7. 结束脚本执行
exit;
?>
如何使用
- 将上面的代码保存为
download.php文件。 - 将您要下载的文件(
my_document.pdf)放到服务器的某个目录,/var/www/html/uploads/。 - 修改
$file变量的值为你的文件的绝对路径。 - 在浏览器中访问
http://你的域名/download.php,浏览器就会自动下载my_document.pdf。
使用 file_get_contents() - 简单但不推荐大文件
这种方法非常简单,直接将整个文件内容读入一个字符串变量,然后再输出。
⚠️ 重要警告
这种方法对于大文件非常危险! 它会将整个文件(例如一个 500MB 的视频)完全加载到服务器的内存中,如果同时有多个用户下载大文件,服务器内存很快就会被耗尽,导致服务器崩溃。
代码示例 (download_fc.php)
<?php
$file = '/var/www/html/uploads/my_document.pdf';
$filename = basename($file);
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
// 读取整个文件到内存
echo file_get_contents($file);
exit;
} else {
die('文件不存在!');
}
?>
除非你确定文件非常小(小于几MB),否则请避免使用这种方法。
提供下载链接(最用户友好)
很多时候,我们并不想直接弹出下载框,而是希望用户点击一个链接后再下载,这非常简单,只需要一个标准的 HTML 说明: 无论使用哪种方法,安全性都是最重要的。 对于绝大多数情况,请优先使用方法一 (<a>
代码示例 (
index.html)<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">文件下载示例</title>
</head>
<body>
<h1>我的文件</h1>
<p>请点击下面的链接下载文件:</p>
<!--
直接指向文件路径即可。
但注意:直接暴露文件路径可能会有安全隐患,用户可能猜到其他文件的路径。
更好的做法是像方法一那样,通过一个 PHP 脚本来处理下载请求。
-->
<a href="/uploads/my_document.pdf" download>下载 my_document.pdf</a>
<hr>
<!-- 更安全的做法:通过 PHP 脚本中转 -->
<p>或者,通过一个安全的 PHP 脚本来下载(推荐):</p>
<a href="download.php">安全下载 my_document.pdf</a>
</body>
</html>

<a href="...">:直接链接到文件,浏览器会根据文件类型决定是打开还是下载(PDF可能会在浏览器内打开)。download 属性:告诉浏览器这是一个下载链接,通常会直接弹出下载框。/uploads/)是不安全的,最佳实践是像方法一那样,创建一个专门的 PHP 下载处理脚本(如 download.php),然后在 HTML 中链接到这个脚本,这样,文件的实际路径就不会被用户直接看到。
安全性最佳实践
/var/www/html/files/...),而不是相对路径(../files/...),以防止路径遍历攻击。readfile() 循环中加入 usleep() 来实现。
方法
优点
缺点
适用场景
readfile()安全、高效、内存友好
代码稍多
所有场景,尤其是大文件下载
file_get_contents()代码简单
内存消耗大,有服务器崩溃风险
仅适用于非常小的文件
HTML
<a>用户最友好,实现简单
可能暴露路径,浏览器行为不可控
作为下载入口,但最终下载逻辑建议用 PHP 处理
readfile()),它兼顾了安全性、性能和可靠性。
