PHP - 下载文件

你好,有抱负的PHP开发者们!今天,我们将深入一个激动人心的话题,这将让你的网站增加一些酷炫的功能——使用PHP下载文件。作为你友好的邻居电脑老师,我将在这一旅程中一步步引导你。所以,拿起你最喜欢的饮料,舒服地坐好,让我们开始编码吧!

PHP - Download File

readfile() 函数

PHP中文件下载的核心是readfile()函数。这个小巧的函数是你读取文件并将其内容写入输出缓冲区的首选工具。现在,别担心这听起来有点技术性——我们将一起分析!

基本用法

让我们从一个简单的例子开始:

<?php
readfile("example.txt");
?>

在这段代码中,readfile()读取"example.txt"的内容并直接输出到浏览器。就像魔法一样——文件的内容出现在你的屏幕上!

下载文件

现在,事情变得有趣了。我们可以使用readfile()来提示文件下载。让我们看一个更完整的例子:

<?php
$file = "myfile.pdf";

if(file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
?>

哇,这需要消化很多信息!让我们分解一下:

  1. 我们指定我们想要下载的文件($file = "myfile.pdf")。
  2. 我们使用file_exists()检查文件是否存在。
  3. 如果文件存在,我们设置一系列的头部信息:
  • Content-Description告诉浏览器这是一个文件传输。
  • Content-Type设置MIME类型为一个通用的二进制文件。
  • Content-Disposition提示浏览器下载文件。
  • 其他头部信息确保文件不会被缓存并正确处理。
  1. 最后,我们使用readfile()输出文件内容。

常见文件类型

不同的文件类型可能需要不同的头部信息。以下是一个常见文件类型及其对应的Content-Type头部信息的便捷表格:

文件类型 Content-Type 头部信息
PDF application/pdf
ZIP application/zip
JPEG image/jpeg
PNG image/png
MP3 audio/mpeg
MP4 video/mp4

创建下载链接

现在我们知道如何触发下载,让我们创建一个用户友好的下载链接:

<!DOCTYPE html>
<html>
<body>

<h2>下载文件</h2>
<p><a href="download.php?file=myfile.pdf">下载PDF</a></p>

</body>
</html>

在这段HTML中,我们创建了一个指向PHP脚本(download.php)的链接,该脚本将处理文件下载。我们将文件名作为URL中的参数传递。

现在,让我们创建download.php脚本:

<?php
if(isset($_GET['file'])) {
$file = $_GET['file'];
$filepath = "uploads/" . $file;

if(file_exists($filepath)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($filepath).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filepath));
readfile($filepath);
exit;
} else {
echo "文件未找到。";
}
}
?>

这个脚本执行以下操作:

  1. 检查URL中是否传递了文件参数。
  2. 构建完整的文件路径(假设文件在"uploads"目录中)。
  3. 如果文件存在,它设置头部信息并触发下载。
  4. 如果文件不存在,它显示一条错误消息。

安全考虑

现在,我知道你在想什么——“但是老师,这有点冒险吧?如果有人尝试下载他们不应该下载的文件怎么办?”好问题!你完全正确,这就是为什么我们需要讨论安全性。

验证文件路径

我们绝不能直接信任用户输入。以下是我们下载脚本的改进版本:

<?php
if(isset($_GET['file'])) {
$file = basename($_GET['file']);
$filepath = "uploads/" . $file;

// 验证文件路径
$realPath = realpath($filepath);
$uploadDir = realpath("uploads/");

if($realPath === false || strpos($realPath, $uploadDir) !== 0) {
die("无效的文件路径。");
}

if(file_exists($filepath)) {
// ...(下载代码的其余部分)
} else {
echo "文件未找到。";
}
}
?>

在这个版本中:

  1. 我们使用basename()来删除任何目录遍历尝试。
  2. 我们使用realpath()来获取文件的实际路径和上传目录的路径。
  3. 我们检查文件的真实路径是否以上传目录路径开始,确保我们不会访问意图之外的目录。

结论

就这样,朋友们!我们已经穿越了PHP文件下载的土地,从readfile()的基础知识到创建下载链接,甚至触及了一些重要的安全考虑。记住,能力越大,责任越大——在处理文件下载时,总是验证用户输入并考虑安全性。

我希望你喜欢这节课,就像我教它一样喜欢。继续练习,继续编码,不久的将来,你将能够创建出带有各种酷炫下载功能的惊人的PHP应用程序。下次见,快乐编码!

Credits: Image by storyset