本文目录导读:

在PHP项目中实现文件上传,主要步骤如下:
创建HTML表单
<!DOCTYPE html>
<html>
<head>文件上传</title>
</head>
<body>
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="fileToUpload" id="fileToUpload">
<input type="submit" value="上传文件" name="submit">
</form>
</body>
</html>
关键点:
method="post":必须使用POST方法enctype="multipart/form-data":必须设置此编码类型
PHP处理上传文件
<?php
// upload.php
// 检查是否有文件上传
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_FILES['fileToUpload'])) {
die('没有文件被上传');
}
$targetDir = "uploads/"; // 上传目录
$targetFile = $targetDir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = true;
$fileType = strtolower(pathinfo($targetFile, PATHINFO_EXTENSION));
// 检查文件是否已存在
if (file_exists($targetFile)) {
echo "抱歉,文件已存在";
$uploadOk = false;
}
// 限制文件大小(例如5MB)
if ($_FILES["fileToUpload"]["size"] > 5 * 1024 * 1024) {
echo "抱歉,文件太大";
$uploadOk = false;
}
// 限制文件类型
$allowedTypes = ['jpg', 'jpeg', 'png', 'gif', 'pdf', 'txt'];
if (!in_array($fileType, $allowedTypes)) {
echo "抱歉,只允许 " . implode(', ', $allowedTypes) . " 格式的文件";
$uploadOk = false;
}
// 检查上传状态
if ($uploadOk) {
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $targetFile)) {
echo "文件 " . basename($_FILES["fileToUpload"]["name"]) . " 上传成功";
} else {
echo "抱歉,上传过程中出现错误";
}
}
?>
完整的增强版本
<?php
class FileUploader {
private $targetDir;
private $maxFileSize;
private $allowedTypes;
private $errors = [];
public function __construct($targetDir = "uploads/", $maxFileSize = 5 * 1024 * 1024) {
$this->targetDir = $targetDir;
$this->maxFileSize = $maxFileSize;
$this->allowedTypes = ['jpg', 'jpeg', 'png', 'gif', 'pdf', 'doc', 'docx', 'txt'];
// 创建上传目录
if (!file_exists($this->targetDir)) {
mkdir($this->targetDir, 0777, true);
}
}
public function upload($file) {
// 验证上传
if ($file['error'] !== UPLOAD_ERR_OK) {
$this->errors[] = $this->getErrorMessage($file['error']);
return false;
}
// 生成唯一文件名
$extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
$newFileName = uniqid() . '_' . time() . '.' . $extension;
$targetFile = $this->targetDir . $newFileName;
// 验证文件类型
if (!in_array($extension, $this->allowedTypes)) {
$this->errors[] = "不允许的文件类型: " . $extension;
return false;
}
// 验证文件大小
if ($file['size'] > $this->maxFileSize) {
$this->errors[] = "文件太大,最大允许 " . ($this->maxFileSize / 1024 / 1024) . "MB";
return false;
}
// 验证是否为真实文件
if (getimagesize($file['tmp_name']) === false && in_array($extension, ['jpg', 'jpeg', 'png', 'gif'])) {
$this->errors[] = "文件不是有效的图片";
return false;
}
// 移动文件
if (move_uploaded_file($file['tmp_name'], $targetFile)) {
return [
'success' => true,
'filename' => $newFileName,
'original_name' => $file['name'],
'path' => $targetFile,
'size' => $file['size'],
'type' => $file['type']
];
} else {
$this->errors[] = "文件移动失败";
return false;
}
}
public function getErrors() {
return $this->errors;
}
private function getErrorMessage($errorCode) {
switch ($errorCode) {
case UPLOAD_ERR_INI_SIZE:
return "上传文件超过PHP配置限制";
case UPLOAD_ERR_FORM_SIZE:
return "上传文件超过表单限制";
case UPLOAD_ERR_PARTIAL:
return "文件仅部分被上传";
case UPLOAD_ERR_NO_FILE:
return "没有文件被上传";
case UPLOAD_ERR_NO_TMP_DIR:
return "服务器缺少临时目录";
case UPLOAD_ERR_CANT_WRITE:
return "文件写入失败";
case UPLOAD_ERR_EXTENSION:
return "文件上传被扩展阻止";
default:
return "未知上传错误";
}
}
}
// 使用示例
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['fileToUpload'])) {
$uploader = new FileUploader();
$result = $uploader->upload($_FILES['fileToUpload']);
if ($result) {
echo "上传成功!";
echo "<br>文件名:" . $result['filename'];
echo "<br>原始名:" . $result['original_name'];
echo "<br>大小:" . round($result['size'] / 1024, 2) . " KB";
} else {
echo "上传失败:";
foreach ($uploader->getErrors() as $error) {
echo "<br>- " . $error;
}
}
}
?>
安全注意事项
// 1. 验证文件内容,不仅仅是扩展名
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $_FILES['file']['tmp_name']);
finfo_close($finfo);
// 2. 使用白名单限制文件类型
$allowedMimeTypes = ['image/jpeg', 'image/png', 'application/pdf'];
// 3. 防止路径遍历攻击
$fileName = basename($_FILES['file']['name']);
$fileName = preg_replace('/[^a-zA-Z0-9._-]/', '', $fileName);
// 4. 设置文件权限
chmod($targetFile, 0644);
// 5. 扫描病毒(可选)
// exec("clamscan " . escapeshellarg($targetFile), $output, $returnVar);
PHP配置优化
; php.ini 相关配置 file_uploads = On upload_max_filesize = 20M post_max_size = 25M max_execution_time = 300 max_input_time = 300 upload_tmp_dir = /tmp
- 创建表单:设置正确的enctype和method
- 接收文件:通过$_FILES获取上传的文件
- 验证文件:检查类型、大小、错误码
- 安全处理:生成唯一文件名,防止路径遍历
- 保存文件:使用move_uploaded_file()移动到目标目录
- 返回结果:告知用户上传成功或失败
这样就能实现一个安全、完整的文件上传功能了。