在PHP开发中,实现光盘下载功能是常见需求,尤其适合资源分享网站,本教程基于实战经验,一步步教你构建安全高效的系统,我们将使用PHP 8.1+、MySQL数据库和Apache服务器,确保代码专业可靠,下面分步详解。

理解PHP文件下载机制
文件下载的核心是PHP的header()函数,它控制HTTP响应头,指定文件类型和下载行为,下载一个ISO镜像文件时,需设置Content-Type为application/octet-stream,并强制浏览器下载而非预览,关键代码片段:
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="disc_image.iso"');
readfile('/path/to/disc_image.iso');
exit;
这确保用户点击链接时直接下载文件,注意:路径必须绝对,避免相对路径错误,实战中,文件应存储在web根目录外(如/var/www/uploads/),防止直接URL访问提升安全。
设置开发环境与数据库
先安装必要工具:PHP 8.1+、MySQL 8.0+和Apache,在Ubuntu系统,运行:
sudo apt update sudo apt install apache2 php mysql-server php-mysql
创建数据库存储光盘信息,假设表名为disc_downloads,结构如下:
CREATE TABLE disc_downloads (
id INT AUTO_INCREMENT PRIMARY KEY,VARCHAR(255) NOT NULL,
file_path VARCHAR(255) NOT NULL,
download_count INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
这表记录光盘标题、文件路径和下载次数,使用PDO连接数据库(防SQL注入):
$dsn = 'mysql:host=localhost;dbname=your_db;charset=utf8'; $pdo = new PDO($dsn, 'username', 'password'); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
实现基本下载功能
构建下载页面:用户从列表选择光盘,点击下载,创建index.php显示光盘列表:

// 查询数据库获取光盘列表
$stmt = $pdo->query("SELECT id, title FROM disc_downloads");
$discs = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 输出列表
foreach ($discs as $disc) {
echo "<a href='download.php?id={$disc['id']}'>{$disc['title']}</a><br>";
}
在download.php中处理下载:
if (isset($_GET['id'])) {
$id = filter_var($_GET['id'], FILTER_SANITIZE_NUMBER_INT);
$stmt = $pdo->prepare("SELECT file_path FROM disc_downloads WHERE id = ?");
$stmt->execute([$id]);
$file = $stmt->fetch(PDO::FETCH_ASSOC);
if ($file) {
$filePath = '/var/www/uploads/' . $file['file_path']; // 实际存储路径
if (file_exists($filePath)) {
// 更新下载次数
$pdo->prepare("UPDATE disc_downloads SET download_count = download_count + 1 WHERE id = ?")->execute([$id]);
// 设置下载头
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
header('Content-Length: ' . filesize($filePath));
readfile($filePath);
exit;
} else {
die("文件不存在!");
}
} else {
die("无效ID!");
}
}
此代码验证ID、确保文件存在,并记录下载次数,使用filter_var()过滤输入,防止XSS攻击。
添加安全性与用户认证
未授权下载可能导致资源滥用,集成基本用户认证:创建用户表users,包含id, username, password(哈希存储),在下载前检查登录状态:
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
// 在download.php开头添加此检查
在login.php实现登录逻辑:
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
$password = $_POST['password'];
$stmt = $pdo->prepare("SELECT id, password FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
$_SESSION['user_id'] = $user['id'];
header('Location: index.php');
} else {
echo "登录失败!";
}
}
使用password_hash()存储密码,确保安全,限制下载速率防DDoS:在.htaccess添加LimitRequestBody 10240000限制大文件请求。
优化下载体验与扩展功能
提升性能:对大文件(如4GB ISO)使用分块下载,避免内存溢出,修改download.php:

$chunkSize = 1024 1024; // 1MB 块
$handle = fopen($filePath, 'rb');
while (!feof($handle)) {
echo fread($handle, $chunkSize);
ob_flush();
flush();
}
fclose($handle);
添加日志记录:在数据库中跟踪用户下载历史,便于分析,扩展表结构:
ALTER TABLE disc_downloads ADD COLUMN user_id INT, ADD FOREIGN KEY (user_id) REFERENCES users(id);
在实际下载时记录用户ID,添加搜索功能:在index.php加入表单,允许按标题搜索光盘,使用LIKE查询加速检索。
完整实战示例
假设光盘文件为ubuntu.iso,存储在/var/www/uploads/,上传脚本upload.php:
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_FILES['disc_file'])) {
$title = filter_input(INPUT_POST, 'title', FILTER_SANITIZE_STRING);
$file = $_FILES['disc_file'];
$targetPath = '/var/www/uploads/' . basename($file['name']);
if (move_uploaded_file($file['tmp_name'], $targetPath)) {
$stmt = $pdo->prepare("INSERT INTO disc_downloads (title, file_path) VALUES (?, ?)");
$stmt->execute([$title, $file['name']]);
echo "上传成功!";
} else {
echo "上传失败!";
}
}
这允许管理员上传新光盘,整个系统部署后,测试下载流程:从登录到下载,确保无缝体验。
你的网站用户反馈过下载速度问题吗?分享你的优化技巧或提问,我们在评论区深入讨论!
原创文章,作者:世雄 - 原生数据库架构专家,如若转载,请注明出处:https://idctop.com/article/18813.html