Appearance
第 13 章:文件上传与图片处理
13.1 文件上传表单
基本表单结构
文件上传表单需要设置 enctype="multipart/form-data" 属性,否则无法上传文件。
html
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="fileToUpload" id="fileToUpload">
<input type="submit" value="上传文件" name="submit">
</form>多文件上传
html
<form action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="files[]" multiple>
<input type="submit" value="上传文件" name="submit">
</form>13.2 $_FILES 获取上传信息
$_FILES 数组结构
当文件上传时,PHP 会将上传文件的信息存储在 $_FILES 超级全局数组中。
单文件上传时的 $_FILES 结构
php
Array(
[fileToUpload] => Array(
[name] => example.jpg // 原始文件名
[type] => image/jpeg // 文件类型
[tmp_name] => /tmp/phpXXXXXX // 临时文件路径
[error] => 0 // 错误码(0 表示成功)
[size] => 102400 // 文件大小(字节)
)
)多文件上传时的 $_FILES 结构
php
Array(
[files] => Array(
[name] => Array(
[0] => file1.jpg
[1] => file2.png
)
[type] => Array(
[0] => image/jpeg
[1] => image/png
)
[tmp_name] => Array(
[0] => /tmp/phpXXXXXX
[1] => /tmp/phpYYYYYY
)
[error] => Array(
[0] => 0
[1] => 0
)
[size] => Array(
[0] => 102400
[1] => 204800
)
)
)13.3 上传验证(大小、类型、重命名)
错误码说明
| 错误码 | 描述 |
|---|---|
| 0 | 上传成功 |
| 1 | 文件大小超过 php.ini 中的 upload_max_filesize 设置 |
| 2 | 文件大小超过表单中的 MAX_FILE_SIZE 设置 |
| 3 | 文件只上传了一部分 |
| 4 | 没有文件被上传 |
| 6 | 缺少临时文件夹 |
| 7 | 文件写入失败 |
上传验证示例
php
<?php
if (isset($_POST["submit"])) {
$target_dir = "uploads/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
// 检查文件是否是图片
if(isset($_POST["submit"])) {
$check = getimagesize($_FILES["fileToUpload"]["tmp_name"]);
if($check !== false) {
echo "文件是图片 - " . $check["mime"] . ".";
$uploadOk = 1;
} else {
echo "文件不是图片.";
$uploadOk = 0;
}
}
// 检查文件是否已存在
if (file_exists($target_file)) {
echo "抱歉,文件已存在.";
$uploadOk = 0;
}
// 检查文件大小
if ($_FILES["fileToUpload"]["size"] > 500000) {
echo "抱歉,您的文件太大.";
$uploadOk = 0;
}
// 允许的文件格式
if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
&& $imageFileType != "gif" ) {
echo "抱歉,只允许 JPG, JPEG, PNG 和 GIF 文件.";
$uploadOk = 0;
}
// 检查 $uploadOk 是否为 0
if ($uploadOk == 0) {
echo "抱歉,您的文件未上传.";
// 尝试上传文件
} else {
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
echo "文件 ". htmlspecialchars( basename( $_FILES["fileToUpload"]["name"])). " 已成功上传.";
} else {
echo "抱歉,上传文件时出错.";
}
}
}
?>文件重命名
为了避免文件名冲突,通常会对上传的文件进行重命名。
php
<?php
$target_dir = "uploads/";
$filename = basename($_FILES["fileToUpload"]["name"]);
$extension = pathinfo($filename, PATHINFO_EXTENSION);
$new_filename = uniqid() . "." . $extension;
$target_file = $target_dir . $new_filename;
// 上传文件
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
echo "文件已成功上传,新文件名: " . $new_filename;
}
?>13.4 头像上传、图片展示
头像上传示例
php
<?php
session_start();
// 检查是否登录
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
$message = '';
$message_type = '';
if (isset($_POST['upload_avatar'])) {
// 检查是否有文件上传
if (!isset($_FILES['avatar']) || $_FILES['avatar']['error'] !== UPLOAD_ERR_OK) {
$message = '请选择要上传的文件';
$message_type = 'error';
} else {
// 设置上传目录
$upload_dir = 'uploads/avatars/';
// 确保目录存在
if (!file_exists($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
// 获取文件信息
$file = $_FILES['avatar'];
$filename = basename($file['name']);
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
// 验证文件类型
$allowed_types = ['jpg', 'jpeg', 'png', 'gif'];
if (!in_array($extension, $allowed_types)) {
$message = '只允许上传 JPG、JPEG、PNG 和 GIF 格式的图片';
$message_type = 'error';
} else {
// 生成唯一文件名
$new_filename = $_SESSION['user_id'] . '.' . $extension;
$target_file = $upload_dir . $new_filename;
// 上传文件
if (move_uploaded_file($file['tmp_name'], $target_file)) {
// 更新用户头像路径到数据库
// 这里应该有数据库更新代码
$message = '头像上传成功';
$message_type = 'success';
// 更新 session 中的头像路径
$_SESSION['avatar'] = $target_file;
} else {
$message = '上传失败,请重试';
$message_type = 'error';
}
}
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>上传头像</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.container {
width: 400px;
margin: 0 auto;
}
.avatar-preview {
width: 150px;
height: 150px;
border-radius: 50%;
overflow: hidden;
margin: 20px 0;
}
.avatar-preview img {
width: 100%;
height: 100%;
object-fit: cover;
}
input[type="file"] {
margin: 10px 0;
}
button {
padding: 8px 16px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
.success {
color: green;
}
.error {
color: red;
}
</style>
</head>
<body>
<div class="container">
<h1>上传头像</h1>
<!-- 显示消息 -->
<?php if (!empty($message)): ?>
<p class="<?php echo $message_type; ?>"><?php echo $message; ?></p>
<?php endif; ?>
<!-- 头像预览 -->
<div class="avatar-preview">
<?php if (isset($_SESSION['avatar']) && file_exists($_SESSION['avatar'])): ?>
<img src="<?php echo $_SESSION['avatar']; ?>" alt="头像">
<?php else: ?>
<img src="https://via.placeholder.com/150" alt="默认头像">
<?php endif; ?>
</div>
<!-- 上传表单 -->
<form method="post" enctype="multipart/form-data">
<input type="file" name="avatar" accept="image/*" required>
<br>
<button type="submit" name="upload_avatar">上传头像</button>
</form>
<p><a href="profile.php">返回个人资料</a></p>
</div>
</body>
</html>图片展示
php
<?php
// 显示上传的图片
$upload_dir = 'uploads/';
$files = scandir($upload_dir);
echo '<h2>上传的图片</h2>';
echo '<div style="display: flex; flex-wrap: wrap;">';
foreach ($files as $file) {
if ($file != '.' && $file != '..') {
$file_path = $upload_dir . $file;
$extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
// 只显示图片文件
if (in_array($extension, ['jpg', 'jpeg', 'png', 'gif'])) {
echo '<div style="margin: 10px;">';
echo '<img src="' . $file_path . '" style="width: 150px; height: 150px; object-fit: cover;">';
echo '<p>' . $file . '</p>';
echo '</div>';
}
}
}
echo '</div>';
?>13.5 实操:用户头像上传
创建 upload-avatar.php 文件
php
<?php
session_start();
// 模拟用户登录
if (!isset($_SESSION['user_id'])) {
$_SESSION['user_id'] = 1;
$_SESSION['username'] = '张三';
}
$message = '';
$message_type = '';
if (isset($_POST['upload_avatar'])) {
// 检查是否有文件上传
if (!isset($_FILES['avatar']) || $_FILES['avatar']['error'] !== UPLOAD_ERR_OK) {
$message = '请选择要上传的文件';
$message_type = 'error';
} else {
// 设置上传目录
$upload_dir = 'uploads/avatars/';
// 确保目录存在
if (!file_exists($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
// 获取文件信息
$file = $_FILES['avatar'];
$filename = basename($file['name']);
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
// 验证文件类型
$allowed_types = ['jpg', 'jpeg', 'png', 'gif'];
if (!in_array($extension, $allowed_types)) {
$message = '只允许上传 JPG、JPEG、PNG 和 GIF 格式的图片';
$message_type = 'error';
} else {
// 生成唯一文件名
$new_filename = $_SESSION['user_id'] . '.' . $extension;
$target_file = $upload_dir . $new_filename;
// 上传文件
if (move_uploaded_file($file['tmp_name'], $target_file)) {
$message = '头像上传成功';
$message_type = 'success';
// 更新 session 中的头像路径
$_SESSION['avatar'] = $target_file;
} else {
$message = '上传失败,请重试';
$message_type = 'error';
}
}
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户头像上传</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.container {
width: 400px;
margin: 0 auto;
padding: 20px;
border: 1px solid #ccc;
border-radius: 5px;
background-color: #f9f9f9;
}
.avatar-preview {
width: 150px;
height: 150px;
border-radius: 50%;
overflow: hidden;
margin: 20px auto;
border: 2px solid #ddd;
}
.avatar-preview img {
width: 100%;
height: 100%;
object-fit: cover;
}
input[type="file"] {
margin: 10px 0;
width: 100%;
}
button {
width: 100%;
padding: 10px;
margin: 10px 0;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 3px;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
.success {
color: green;
text-align: center;
}
.error {
color: red;
text-align: center;
}
h1 {
text-align: center;
color: #333;
}
</style>
</head>
<body>
<div class="container">
<h1>用户头像上传</h1>
<!-- 显示消息 -->
<?php if (!empty($message)): ?>
<p class="<?php echo $message_type; ?>"><?php echo $message; ?></p>
<?php endif; ?>
<!-- 头像预览 -->
<div class="avatar-preview">
<?php if (isset($_SESSION['avatar']) && file_exists($_SESSION['avatar'])): ?>
<img src="<?php echo $_SESSION['avatar']; ?>" alt="头像">
<?php else: ?>
<img src="https://via.placeholder.com/150" alt="默认头像">
<?php endif; ?>
</div>
<!-- 上传表单 -->
<form method="post" enctype="multipart/form-data">
<input type="file" name="avatar" accept="image/*" required>
<button type="submit" name="upload_avatar">上传头像</button>
</form>
<p style="text-align: center;"><a href="#">返回个人中心</a></p>
</div>
</body>
</html>访问页面
- 将文件保存到网站根目录
- 确保
uploads/avatars/目录存在且有写入权限 - 打开浏览器,访问
http://localhost/upload-avatar.php - 测试头像上传功能
小结
通过本章的学习,你掌握了 PHP 文件上传的基本方法,包括创建文件上传表单、获取上传文件信息、验证文件、重命名文件以及处理图片上传。这些知识在开发用户头像上传、文件管理等功能时非常重要。在后续的实战项目中,你将使用这些技术来实现文件上传和图片处理功能。
