本文目录导读:

在PHP中实现文件下载功能有多种方法,下面我介绍几种常见的实现方式。
基本文件下载(直接链接)
最简单的下载方式,文件放在服务器可访问的目录:
// 文件在服务器上的路径
$file = 'path/to/your/file.pdf';
$filename = 'download.pdf'; // 下载时显示的文件名
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));
readfile($file);
exit;
}
通过URL参数下载(常见方式)
<?php
// download.php?id=123
$fileId = $_GET['id'];
// 从数据库获取文件信息
$fileInfo = getFileInfoFromDatabase($fileId); // 自定义函数
$file = 'uploads/' . $fileInfo['stored_name'];
$filename = $fileInfo['original_name'];
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));
// 清空输出缓冲
ob_clean();
flush();
// 输出文件内容
readfile($file);
exit;
} else {
echo '文件不存在';
}
?>
大文件下载(分块传输)
对于大文件,使用分块传输避免内存溢出:
function downloadFile($file, $filename = null) {
if (!file_exists($file)) {
return false;
}
if (!$filename) {
$filename = basename($file);
}
// 获取文件大小
$fileSize = filesize($file);
// 设置下载头
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . $fileSize);
// 清空输出缓冲
ob_clean();
flush();
// 打开文件
$handle = fopen($file, 'rb');
// 分块读取并输出
$chunkSize = 1024 * 1024; // 1MB
while (!feof($handle)) {
echo fread($handle, $chunkSize);
ob_flush();
flush();
}
fclose($handle);
exit;
}
// 使用示例
downloadFile('large_file.mp4', '我的视频.mp4');
断点续传下载
function resumeDownload($file, $filename = null) {
if (!file_exists($file)) {
return false;
}
if (!$filename) {
$filename = basename($file);
}
$fileSize = filesize($file);
$start = 0;
$end = $fileSize - 1;
// 处理断点续传
if (isset($_SERVER['HTTP_RANGE'])) {
$range = $_SERVER['HTTP_RANGE'];
$range = str_replace('bytes=', '', $range);
$range = explode('-', $range);
if (isset($range[0]) && $range[0] !== '') {
$start = intval($range[0]);
}
if (isset($range[1]) && $range[1] !== '') {
$end = intval($range[1]);
}
header('HTTP/1.1 206 Partial Content');
header('Content-Range: bytes ' . $start . '-' . $end . '/' . $fileSize);
} else {
header('HTTP/1.1 200 OK');
}
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Length: ' . ($end - $start + 1));
$handle = fopen($file, 'rb');
fseek($handle, $start);
$chunkSize = 1024 * 1024;
$remaining = ($end - $start + 1);
while ($remaining > 0) {
$readSize = min($chunkSize, $remaining);
echo fread($handle, $readSize);
$remaining -= $readSize;
ob_flush();
flush();
}
fclose($handle);
exit;
}
下载不同类型的文件
根据文件类型设置正确的MIME类型:
function getMimeType($file) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $file);
finfo_close($finfo);
return $mimeType;
}
function downloadWithCorrectType($file, $filename = null) {
if (!file_exists($file)) {
return false;
}
if (!$filename) {
$filename = basename($file);
}
$mimeType = getMimeType($file);
header('Content-Description: File Transfer');
header('Content-Type: ' . $mimeType);
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
HTML下载按钮示例
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>文件下载</title>
</head>
<body>
<h2>文件下载</h2>
<ul>
<li>
<a href="download.php?id=1">下载文档1.pdf</a>
</li>
<li>
<a href="download.php?id=2">下载图片2.jpg</a>
</li>
<li>
<form action="download.php" method="post">
<input type="hidden" name="file_id" value="3">
<button type="submit">下载视频3.mp4</button>
</form>
</li>
</ul>
</body>
</html>
重要注意事项
- 安全性:始终验证用户是否有权限下载文件
- 路径安全:防止目录遍历攻击
- 文件验证:确保文件存在且可读
- 大文件处理:使用分块传输处理大文件
- 错误处理:添加适当的错误处理机制
// 安全验证示例
function validateDownload($fileId, $userId) {
// 验证用户权限
if (!hasPermission($userId, 'download')) {
return false;
}
// 验证文件属于该用户
$file = getFileById($fileId);
if ($file['user_id'] !== $userId) {
return false;
}
return true;
}
// 防止目录遍历
function sanitizeFilename($filename) {
$filename = basename($filename);
$filename = str_replace(['../', '..\\', './', '.\\'], '', $filename);
$filename = preg_replace('/[^\w\-_\. ]/', '', $filename);
return $filename;
}
选择合适的下载方式取决于你的具体需求:小文件用简单方法,大文件用分块传输,需要续传功能用断点续传实现。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播