
下面我将提供一个完整的PHP文件上传与下载的实现方案,包含前端表单、后端处理代码和安全措施。
文件上传实现
1. 前端HTML表单
<!DOCTYPE html><html><head>
<title>文件上传与下载</title></head><body>
<h2>文件上传</h2>
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="fileToUpload" id="fileToUpload">
<input type="submit" value="上传文件" name="submit">
</form>
<h2>文件下载</h2>
<?php
// 显示可下载文件列表
$files = scandir('uploads');
foreach($files as $file) {
if($file !== '.' && $file !== '..') {
echo "<p><a href='download.php?file=".urlencode($file)."'>$file</a></p>";
}
}
?></body></html>2. 文件上传处理 (upload.php)
<?php// 上传目录$uploadDir = 'uploads/';// 创建上传目录(如果不存在)if (!file_exists($uploadDir)) {
mkdir($uploadDir, 0777, true);}// 检查文件是否上传成功if(isset($_POST["submit"])) {
$targetFile = $uploadDir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$fileType = strtolower(pathinfo($targetFile, PATHINFO_EXTENSION));
// 检查文件是否已存在
if (file_exists($targetFile)) {
echo "抱歉,文件已存在。";
$uploadOk = 0;
}
// 限制文件大小 (5MB)
if ($_FILES["fileToUpload"]["size"] > 5000000) {
echo "抱歉,文件太大。";
$uploadOk = 0;
}
// 允许的文件格式
$allowedTypes = array('jpg', 'png', 'jpeg', 'gif', 'pdf', 'doc', 'docx', 'txt');
if(!in_array($fileType, $allowedTypes)) {
echo "抱歉,只允许上传 JPG, JPEG, PNG, GIF, PDF, DOC, DOCX, TXT 文件。";
$uploadOk = 0;
}
// 检查上传标志
if ($uploadOk == 0) {
echo "抱歉,文件未上传。";
} else {
// 尝试上传文件
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $targetFile)) {
echo "文件 ". htmlspecialchars(basename($_FILES["fileToUpload"]["name"])). " 上传成功。";
// 重定向回上传页面
header("Refresh: 2; URL=index.php");
} else {
echo "抱歉,上传文件时出错。";
}
}}?>3. 文件下载处理 (download.php)
<?php// 下载目录(必须与上传目录相同)$downloadDir = 'uploads/';if(isset($_GET['file'])) {
$fileName = basename($_GET['file']);
$filePath = $downloadDir . $fileName;
// 检查文件是否存在
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));
// 清除输出缓冲
flush();
// 读取文件并输出到浏览器
readfile($filePath);
exit;
} else {
http_response_code(404);
die('文件不存在');
}} else {
die('无效的文件名');}?>安全增强措施
1. 文件上传安全增强
// 在upload.php中添加以下检查// 检查文件是否是真实的图片(仅对图片有效)if(isset($_POST["submit"])) {
$check = getimagesize($_FILES["fileToUpload"]["tmp_name"]);
if($check !== false) {
// 是图片
} else {
echo "文件不是图片。";
$uploadOk = 0;
}}// 防止文件名注入攻击$fileName = preg_replace("/[^A-Za-z0-9\.]/", "", $_FILES["fileToUpload"]["name"]);$targetFile = $uploadDir . $fileName;// 生成随机文件名$newFileName = uniqid() . '.' . $fileType;$targetFile = $uploadDir . $newFileName;2. 文件下载安全增强
// 在download.php中添加以下检查// 防止目录遍历攻击$fileName = basename($_GET['file']);$filePath = realpath($downloadDir . $fileName);// 确保文件在指定目录内if(strpos($filePath, realpath($downloadDir)) !== 0) {
die('非法文件访问');}// 检查文件类型并提供正确的Content-Type$fileExtension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));$contentTypes = [
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
'pdf' => 'application/pdf',
'doc' => 'application/msword',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'txt' => 'text/plain'];if(array_key_exists($fileExtension, $contentTypes)) {
header('Content-Type: ' . $contentTypes[$fileExtension]);} else {
header('Content-Type: application/octet-stream');}完整类封装版本
文件上传下载类 (FileHandler.php)
<?phpclass FileHandler {
private $uploadDir;
private $allowedTypes;
private $maxFileSize;
public function __construct($uploadDir = 'uploads/', $allowedTypes = array(), $maxFileSize = 5000000) {
$this->uploadDir = rtrim($uploadDir, '/') . '/';
$this->allowedTypes = $allowedTypes ?: array('jpg', 'png', 'jpeg', 'gif', 'pdf', 'doc', 'docx', 'txt');
$this->maxFileSize = $maxFileSize;
// 创建上传目录
if (!file_exists($this->uploadDir)) {
mkdir($this->uploadDir, 0777, true);
}
}
public function upload($fileInputName) {
if (!isset($_FILES[$fileInputName])) {
return ['success' => false, 'message' => '没有文件被上传'];
}
$file = $_FILES[$fileInputName];
// 检查上传错误
if ($file['error'] !== UPLOAD_ERR_OK) {
return ['success' => false, 'message' => $this->getUploadError($file['error'])];
}
// 检查文件大小
if ($file['size'] > $this->maxFileSize) {
return ['success' => false, 'message' => '文件太大'];
}
// 获取文件扩展名
$fileExt = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
// 检查文件类型
if (!in_array($fileExt, $this->allowedTypes)) {
return ['success' => false, 'message' => '不允许的文件类型'];
}
// 生成安全文件名
$safeName = $this->generateSafeName($file['name']);
$targetPath = $this->uploadDir . $safeName;
// 移动上传的文件
if (move_uploaded_file($file['tmp_name'], $targetPath)) {
return [
'success' => true,
'message' => '文件上传成功',
'filePath' => $targetPath,
'fileName' => $safeName
];
} else {
return ['success' => false, 'message' => '文件移动失败'];
}
}
public function download($fileName) {
$filePath = realpath($this->uploadDir . basename($fileName));
// 安全检查
if (!file_exists($filePath)) {
return ['success' => false, 'message' => '文件不存在'];
}
if (strpos($filePath, realpath($this->uploadDir)) !== 0) {
return ['success' => false, 'message' => '非法文件访问'];
}
// 获取文件信息
$fileExt = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
$fileSize = filesize($filePath);
$contentType = $this->getContentType($fileExt);
// 设置头部信息
header('Content-Description: File Transfer');
header('Content-Type: ' . $contentType);
header('Content-Disposition: attachment; filename="'.basename($filePath).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . $fileSize);
// 输出文件
readfile($filePath);
exit;
}
public function listFiles() {
$files = scandir($this->uploadDir);
return array_filter($files, function($file) {
return $file !== '.' && $file !== '..';
});
}
private function generateSafeName($fileName) {
$extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
$baseName = md5(uniqid() . microtime(true));
return $baseName . '.' . $extension;
}
private function getUploadError($errorCode) {
$errors = [
UPLOAD_ERR_INI_SIZE => '文件超过了php.ini中upload_max_filesize限制',
UPLOAD_ERR_FORM_SIZE => '文件超过了表单MAX_FILE_SIZE限制',
UPLOAD_ERR_PARTIAL => '文件只有部分被上传',
UPLOAD_ERR_NO_FILE => '没有文件被上传',
UPLOAD_ERR_NO_TMP_DIR => '找不到临时文件夹',
UPLOAD_ERR_CANT_WRITE => '文件写入失败',
UPLOAD_ERR_EXTENSION => 'PHP扩展阻止了文件上传'
];
return $errors[$errorCode] ?? '未知上传错误';
}
private function getContentType($extension) {
$types = [
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
'pdf' => 'application/pdf',
'doc' => 'application/msword',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'txt' => 'text/plain'
];
return $types[$extension] ?? 'application/octet-stream';
}}使用封装类
<?php// 使用示例require_once 'FileHandler.php';// 初始化文件处理器$fileHandler = new FileHandler('uploads/', ['jpg', 'png', 'pdf'], 2 * 1024 * 1024); // 2MB限制// 处理上传if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['fileToUpload'])) {
$result = $fileHandler->upload('fileToUpload');
if ($result['success']) {
echo "文件上传成功: " . $result['fileName'];
} else {
echo "上传失败: " . $result['message'];
}
exit;}// 处理下载if (isset($_GET['download'])) {
$result = $fileHandler->download($_GET['download']);
if (!$result['success']) {
echo $result['message'];
}
exit;}// 显示文件列表$files = $fileHandler->listFiles();?><!DOCTYPE html><html><head>
<title>文件上传与下载</title></head><body>
<h2>文件上传</h2>
<form method="post" enctype="multipart/form-data">
<input type="file" name="fileToUpload">
<button type="submit">上传</button>
</form>
<h2>文件列表</h2>
<ul>
<?php foreach ($files as $file): ?>
<li>
<?php echo htmlspecialchars($file); ?>
<a href="?download=<?php echo urlencode($file); ?>">下载</a>
</li>
<?php endforeach; ?>
</ul></body></html>总结
这个完整的PHP文件上传下载实现包含以下特点:
文件上传功能:
支持多种文件类型
文件大小限制
防止文件名注入
生成随机文件名增强安全性
文件下载功能:
安全的文件路径检查
正确的Content-Type设置
防止目录遍历攻击
封装类版本:
面向对象设计
可配置的文件类型和大小限制
统一的错误处理
文件列表功能
安全措施:
文件类型检查
文件内容验证(对图片)
安全的文件名处理
防止目录遍历
您可以根据实际需求调整配置参数,或者扩展类的功能。这个实现适合大多数Web应用的文件上传下载需求。
希望以上内容对你有所帮助!如果还有其他问题,请随时提问。 各类知识收集 拥有多年CMS企业建站经验,对 iCMS, LeCMS, ClassCMS, Fastadmin, PbootCMS, PHPCMS, 易优CMS, YzmCMS, 讯睿CMS, 极致CMS, Wordpress, HkCMS, YznCMS, WellCMS, ThinkCMF, 等各类cms的相互转化,程序开发,网站制作,bug修复,程序杀毒,插件定制都可以提供最佳解决方案。


