服务端 - PHP - 文件操作之文件上传
一、常见的文件上传配置项
序号 |
配置项 |
默认值 |
描述 |
1 |
file_uploads |
On |
使 PHP 支持文件上传 |
2 |
upload_tmp_dir |
/tmp |
指示应该临时把上传的文件存储在什么位置 |
3 |
max_file_uploads |
20 |
单次请求时允许上传的最大文件数量 |
4 |
max_execution_time |
30 |
设置 PHP 最长执行时间(秒) |
5 |
max_input_time |
60 |
设置 PHP 通过 POST/GET/PUT 接收数据的时长(秒) |
6 |
memory_limit |
128M |
系统分配给当前脚本执行可用的最大内存容量 |
7 |
post_max_size |
8M |
允许的 POST 数据的总大小(以字节为单位) |
8 |
upload_max_filesize |
32M |
允许的尽可能最大的文件上传(以字节为单位) |
二、$_FILES
全局变量
1. 5个属性
序号 |
键名 |
描述 |
1 |
name |
文件在客户端的原始文件名(即存在用户电脑上的文件名) |
2 |
type |
文件的 MIME 类型, 由浏览器提供, PHP 并不检查它 |
3 |
tmp_name |
文件被上传到服务器上之后,在临时目录中临时文件名 |
4 |
error |
和该文件上传相关的错误代码 |
5 |
size |
已上传文件的大小(单位为字节) |
2. 文件上传错误信息描述
序号 |
常量 |
值 |
描述 |
1 |
UPLOAD_ERR_OK |
0 |
没有错误发生,文件上传成功 |
2 |
UPLOAD_ERR_INI_SIZE |
1 |
文件超过php.ini 中upload_max_filesize 值 |
3 |
UPLOAD_ERR_FORM_SIZE |
2 |
文件大小超过表单中MAX_FILE_SIZE 指定的值 |
4 |
UPLOAD_ERR_PARTIAL |
3 |
文件只有部分被上传 |
5 |
UPLOAD_ERR_NO_FILE |
4 |
没有文件被上传 |
6 |
UPLOAD_ERR_NO_TMP_DIR |
6 |
找不到临时文件夹 |
7 |
UPLOAD_ERR_CANT_WRITE |
7 |
文件写入失败 |
3. 支持文件上传的前端表单设置
序号 |
属性设置 |
描述 |
1 |
<form method="POST"> |
请求类型必须是POST |
2 |
<form enctype="multipart/form-data"> |
设置表单提交数据的编码类型 |
3 |
<input type="file" name="uploads"> |
设置表单控件类型与名称以支持上传 |
4 |
<input type="hidden" name="MAX_FILE_SIZE" value="..."> |
设置隐藏域限制上传文件大小(可选) |
4. 设置表单数据,在发送到服务器之前的编码规则
序号 |
属性值 |
描述 |
1 |
application/x-www-form-urlencoded |
默认值, 发送前进行编码,空格转+ ,非空字符转 16 进制 |
2 |
multipart/form-data |
不对字符编码,以二进制发送,适合文件上传 |
3 |
text/plain |
纯文本发送,仅对空格编码(转为+ ) |
三、实现
1. 单文件上传
<!DOCTYPE html>
<html lang="zh_hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>单文件上传</title>
</head>
<body>
<div class="a-box">
<form action="" method="POST" enctype="multipart/form-data">
<fieldset>
<!--在文件上传至服务器之前对文件大小进行限制-->
<input type="hidden" name="MAX_FILE_SIZE" value="300000">
<input type="file" name="pic">
<button>上传</button>
</fieldset>
</form>
</div>
</body>
</html>
<?php
//1. 自定义上传异常类
class UploadException extends Exception {
public function __toString()
{
return <<< UPLOAD
<p>代码:$this->code; 错误信息:$this->message; 文件:$this->file; 行:$this->line</p>
UPLOAD;
}
};
//2. 进行异常处理
try {
//2.1 获取错误代码
$error_code = $_FILES['pic']['error'];
//2.2 根据错误代码作异常处理
if ($error_code > UPLOAD_ERR_OK) {
switch ($error_code) {
case 1:
throw new UploadException('文件大小超过服务端限制', 1);
break;
case 2:
throw new UploadException('文件大小超过客户端限制', 2);
break;
case 3:
throw new UploadException('文件只有部分被上传', 3);
break;
case 4:
throw new UploadException('文件上传失败', 4);
break;
case 6:
throw new UploadException('找不到临时文件夹', 6);
break;
case 7:
throw new UploadException('文件写入失败', 7);
break;
default:
throw new UploadException('未知类型错误', 8);
}
}
//2.3 判断文件类型
$file_type = $_FILES['pic']['type'];
if (strstr($file_type, '/', true) !== 'image') {
throw new UploadException('文件类型错误', 9);
}
//3. 移动文件到目标目录
//3.1 获取临时文件名
$tmp_file_name = $_FILES['pic']['tmp_name'];
//3.2 获取原始文件名
$ori_file_name = $_FILES['pic']['name'];
//3.3 创建目录文件名
$dest_file_name = 'uploads/'.md5(time().mt_rand(1,1000)).strstr($ori_file_name, '.');
if (move_uploaded_file($tmp_file_name, $dest_file_name)) {
echo '<script>alert("文件上传成功");</script>';
//4. 预览
echo "<img src='$dest_file_name' width='200'>";
}
} catch (UploadException $e) {
echo $e;
}
?>
2. 多文件上传
<!DOCTYPE html>
<html lang="zh_hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>多文件上传</title>
</head>
<body>
<div class="a-box">
<form action="" method="POST" enctype="multipart/form-data">
<fieldset>
<!--在文件上传至服务器之前对文件大小进行限制-->
<input type="hidden" name="MAX_FILE_SIZE" value="300000">
<input type="file" name="pic[]">
<input type="file" name="pic[]">
<input type="file" name="pic[]">
<input type="file" name="pic[]">
<button>上传</button>
</fieldset>
</form>
</div>
</body>
</html>
<?php
//1. 自定义上传异常类
class UploadException extends Exception {
public function __toString()
{
return <<< UPLOAD
<p>代码:$this->code; 错误信息:$this->message; 文件:$this->file; 行:$this->line</p>
UPLOAD;
}
};
//2. 进行异常处理
try {
if ($_FILES['pic']) {
//取出错误码
foreach ($_FILES['pic']['error'] as $key => $error_code) {
if ($error_code > UPLOAD_ERR_OK) {
switch ($error_code) {
case 1:
throw new UploadException('文件大小超过服务端限制', 1);
break;
case 2:
throw new UploadException('文件大小超过客户端限制', 2);
break;
case 3:
throw new UploadException('文件只有部分被上传', 3);
break;
case 4:
throw new UploadException('文件上传失败', 4);
break;
case 6:
throw new UploadException('找不到临时文件夹', 6);
break;
case 7:
throw new UploadException('文件写入失败', 7);
break;
default:
throw new UploadException('未知类型错误', 8);
}
} else {
//判断文件类型
foreach ($_FILES['pic']['type'] as $file_type) {
if (strstr($file_type, '/', true) !== 'image') {
throw new UploadException('文件类型错误', 9);
}
}
}
//3. 移动文件
if ($error_code === 0) {
$tmp_file_name = $_FILES['pic']['tmp_name'][$key];
$ori_file_name = $_FILES['pic']['name'][$key];
$dest_file_name = 'uploads/'.md5(time().mt_rand(1, 1000)).strstr($ori_file_name, '.');
if (move_uploaded_file($tmp_file_name, $dest_file_name)) {
//4. 预览
echo "<img src='$dest_file_name' width='200'>";
}
}
};
echo '<script>alert("文件上传成功");</script>';
}
} catch (Exception $e) {
echo $e;
}
?>
3. 批量上传
<!DOCTYPE html>
<html lang="zh_hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>批量上传</title>
</head>
<body>
<div class="a-box">
<form action="" method="POST" enctype="multipart/form-data">
<fieldset>
<!--在文件上传至服务器之前对文件大小进行限制-->
<input type="hidden" name="MAX_FILE_SIZE" value="300000">
<input type="file" name="pic[]" multiple>
<button>上传</button>
</fieldset>
</form>
</div>
</body>
</html>
<?php
//1. 自定义上传异常类
class UploadException extends Exception {
public function __toString()
{
return <<< UPLOAD
<p>代码:$this->code; 错误信息:$this->message; 文件:$this->file; 行:$this->line</p>
UPLOAD;
}
};
//2. 进行异常处理
try {
if ($_FILES['pic']) {
//取出错误码
foreach ($_FILES['pic']['error'] as $key => $error_code) {
if ($error_code > UPLOAD_ERR_OK) {
switch ($error_code) {
case 1:
throw new UploadException('文件大小超过服务端限制', 1);
break;
case 2:
throw new UploadException('文件大小超过客户端限制', 2);
break;
case 3:
throw new UploadException('文件只有部分被上传', 3);
break;
case 4:
throw new UploadException('文件上传失败', 4);
break;
case 6:
throw new UploadException('找不到临时文件夹', 6);
break;
case 7:
throw new UploadException('文件写入失败', 7);
break;
default:
throw new UploadException('未知类型错误', 8);
}
} else {
//判断文件类型
foreach ($_FILES['pic']['type'] as $file_type) {
if (strstr($file_type, '/', true) !== 'image') {
throw new UploadException('文件类型错误', 9);
}
}
}
//3. 移动文件
if ($error_code === 0) {
$tmp_file_name = $_FILES['pic']['tmp_name'][$key];
$ori_file_name = $_FILES['pic']['name'][$key];
$dest_file_name = 'uploads/'.md5(time().mt_rand(1, 1000)).strstr($ori_file_name, '.');
if (move_uploaded_file($tmp_file_name, $dest_file_name)) {
//4. 预览
echo "<img src='$dest_file_name' width='200'>";
}
}
};
echo '<script>alert("文件上传成功");</script>';
}
} catch (Exception $e) {
echo $e;
}
?>
四、课程总结
- 今天学习了 PHP 的文件上传,通过上课认真听讲和认真完成老师布置的作业,使得我对 PHP 文件操作的理解和运用更加深入和熟悉。最主要的知识点是明白和掌握了文件上传的特点以及它的基本用法。
Correcting teacher:天蓬老师
Correction status:qualified
Teacher's comments:文件上传非常重要, 也非常有意思, 更是一个完全隐患, 重视起来