Correcting teacher:天蓬老师
Correction status:qualified
Teacher's comments:你写了一天, 是前戏不足呀, 我与教案整整资料用了大半天, 写起来很快的
文件上传演示地址http://php.rc238.cn/0511
文件上传项目项在
php.ini
中设置,常用的配置项有:
序号 | 配置项 | 默认值 | 描述 |
---|---|---|---|
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
$_FILES
中$_FILES
以二维数组形式保存: $_FILES['form_file_name']['key']
'form_file_name'
: 对应着表单中<input type="file" name="my_pic">
中name
属性值'key'
: 共有 5 个键名, 描述如下:序号 | 键名 | 描述 |
---|---|---|
1 | name |
文件在客户端的原始文件名(即存在用户电脑上的文件名) |
2 | type |
文件的 MIME 类型, 由浏览器提供, PHP 并不检查它 |
3 | tmp_name |
文件被上传到服务器上之后,在临时目录中临时文件名 |
4 | error |
和该文件上传相关的错误代码 |
5 | size |
已上传文件的大小(单位为字节) |
序号 | 常量 | 值 | 描述 |
---|---|---|---|
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 |
文件写入失败 |
序号 | 属性设置 | 描述 |
---|---|---|
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="..."> |
设置隐藏域限制上传文件大小(可选) |
enctype
属性说明
enctype
: 设置表单数据,在发送到服务器之前的编码规则
序号 | 属性值 | 描述 |
---|---|---|
1 | application/x-www-form-urlencoded |
默认值, 发送前进行编码,空格转+ ,非空字符转 16 进制 |
2 | multipart/form-data |
不对字符编码,以二进制发送,适合文件上传 |
3 | text/plain |
纯文本发送,仅对空格编码(转为+ ) |
Email
附件格式的字符串, 后来演变成为网络文档或应用程序的文档格式规范/
分隔,例如text/css
序号 | 类型 | 描述 | 示例 |
---|---|---|---|
1 | text |
文本 | text/plain ,text/html ,text/css ,text/javascript |
2 | image |
图像 1 | image/jpeg ,image/gif ,image/png ,image/bmp ,image/ webp , |
2 | image |
图像 2 | image/x-icon , image/vnd.microsoft.icon |
3 | audio |
音频 | audio/midi , audio/mpeg , audio/webm , audio/ogg , audio/wav |
4 | video |
视频 | video/mp4 ,video/mpeg ,video/webm , video/ogg ,video/x-msvideo |
5 | application |
二进制 1 | application/octet-stream , application/javascript , application/ecmascript |
5 | application |
二进制 2 | application/json ,application/pkcs12 , application/vnd.mspowerpoint |
5 | application |
二进制 3 | application/xhtml+xml , application/xml , application/pdf ,application/x-gzip |
x-
为前缀的是还没有成为国际标准的格式applicaton/octet-stream
, 如.md
文档, 尽管它是纯文本html 部分
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="index.css" />
<title>单文件上传</title>
</head>
<body>
<img src="http://pic1.win4000.com/wallpaper/e/57bff123d2e05.jpg" alt="" />
<section>
<form action="?mode=single" method="post" enctype="multipart/form-data">
<fieldset>
<legend>单文件上传</legend>
<input type="file" name="my_pic" />
<button>上传</button>
</fieldset>
</form>
<form action="?mode=multiple" method="post" enctype="multipart/form-data">
<fieldset>
<legend>多文件上传</legend>
<input type="file" name="my_pic1" required />
<input type="file" name="my_pic2" required />
<input type="file" name="my_pic3" required />
<button>上传</button>
</fieldset>
</form>
<form action="?mode=batch" method="post" enctype="multipart/form-data">
<fieldset>
<legend>批量上传</legend>
<input type="file" name="my_pic[]" multiple required />
<button>上传</button>
</fieldset>
</form>
</section>
<section>
<?php
require 'handle.php';
?>
</section>
</body>
</html>
css 部分
* {
margin: 0px;
padding: 0px;
box-sizing: border-box;
}
body {
min-height: 100vh;
min-width: 100vw;
}
body > img {
position: fixed;
top: 0;
left: 0;
z-index: -1;
width: 100%;
height: 100%;
}
section:first-of-type {
background-color: #fff;
width: 800px;
margin: 50px auto 0px;
padding: 20px;
opacity: 0.7;
}
fieldset {
border: 1px solid #ccc;
text-align: center;
padding: 20px 0px;
}
legend {
color: green;
margin: auto;
}
fieldset > input {
border: none;
padding: 5px;
color: lime;
width: 120px;
}
fieldset > button {
width: 60px;
height: 25px;
border: none;
border-radius: 10px;
background-color: lightskyblue;
}
fieldset > button:hover {
background-color: magenta;
}
section:last-of-type > div {
width: 800px;
margin: 20px auto;
display: flex;
flex-flow: row nowrap;
background-color: lightgrey;
padding: 10px;
border-radius: 10px;
}
section:last-of-type > div > img {
width: 80px;
margin-right: 20px;
}
php 部分
<?php
//创建一个异常类 抛出异常
class FileException extends Exception
{
public
function __toString()
{
return <<< AAA
<script>
alert('{$this->message}');
</script>
AAA;
}
}
try {
//创建类 把方式,文件名传进去处理
class FileHandle
{
// 接收数据
public function __construct($Tmp_FileName, $DestFileName, $fileType, $i)
{
$this->set($Tmp_FileName, $DestFileName, $fileType, $i);
}
//创建保存文件方法
public function set($Tmp_FileName, $DestFileName, $fileType, $i)
{
if ($fileType === 'image') {
if (move_uploaded_file($Tmp_FileName, $DestFileName)) {
echo "<div><img src='{$DestFileName}' width='200'>";
echo '<p>文件上传成功</p></div>';
}
} else {
$err = '第' . $i . '个文件类型错误,终止上传';
throw new FileException($err);
}
}
}
//创建变量
//文件异常码
$errorcode = '';
//文件类型 image/jpge 切割一下只要前面的image
$fileType = '';
//原始文件名
$OriginalFileName = '';
//临时文件名
$Tmp_FileName = '';
// 目录文件名 加密一下
$DestFileName = '';
//赋值 如果是get才执行
if ($_GET) {
// 获取当前上传方式 ?mode = 单文件single 多文件 multiple 批量 batch
$mode = strtolower($_GET['mode']);
$i = 1;
// 判断get值
switch ($mode) {
### get=single
case 'single':
$errorcode = $_FILES['my_pic']['error'];
$fileType = strstr($_FILES['my_pic']['type'], '/', true);
$OriginalFileName = $_FILES['my_pic']['name'];
$Tmp_FileName = $_FILES['my_pic']['tmp_name'];
$DestFileName = 'uploads/' . md5(sha1(time() . mt_rand(1, 1000))) . strstr($OriginalFileName, '.');
if (is_uploaded_file($Tmp_FileName)) {
// 执行类实例
new FileHandle($Tmp_FileName, $DestFileName, $fileType, $i);
}
break;
### get=multiple
case 'multiple':
// 遍历数组 每个子数组给别名$file
foreach ($_FILES as $file) {
$errorcode = $file['error'];
$fileType = strstr($file['type'], '/', true);
$OriginalFileName = $file['name'];
$Tmp_FileName = $file['tmp_name'];
$DestFileName = 'uploads/' . md5(sha1(time() . mt_rand(1, 1000))) . strstr($OriginalFileName, '.');
if (is_uploaded_file($Tmp_FileName)) {
// 执行类实例
new FileHandle($Tmp_FileName, $DestFileName, $fileType, $i++);
}
}
break;
### get=batch
case 'batch':
if ($_FILES['my_pic']) {
foreach ($_FILES['my_pic']['error'] as $key => $error) {
if ($error === 0) {
$errorcode = $_FILES['my_pic']['error'][$key];
$fileType = strstr($_FILES['my_pic']['type'][$key], '/', true);
$OriginalFileName = $_FILES['my_pic']['name'][$key];;
$Tmp_FileName = $_FILES['my_pic']['tmp_name'][$key];
$DestFileName = 'uploads/' . md5(sha1(time() . mt_rand(1, 1000))) . strstr($OriginalFileName, '.');
if (is_uploaded_file($Tmp_FileName)) {
// 执行类实例
new FileHandle($Tmp_FileName, $DestFileName, $fileType, $i++);
}
}
}
}
break;
default:
echo <<< BBB
<script>
alert('非法的参数请求');
location.href='index.php';
</script>
BBB;
}
}
if ($errorcode > 0) {
switch ($errorcode) {
case 1:
throw new FileException('上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值', 1);
break;
case 2:
throw new FileException('上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值', 2);
break;
case 3:
throw new FileException('文件只有部分被上传', 3);
break;
case 4:
throw new FileException('当前没有文件被上传', 4);
break;
case 6:
throw new FileException('找不到临时文件夹', 6);
break;
case 7:
throw new FileException('文件写入失败', 8);
break;
default:
throw new FileException('未知错误', 10);
}
}
} catch (FileException $e) {
echo $e;
}
?>
写个这个忙活一天,代码删了写 写了删 写到最后又感觉前面有些代码冗余 又重构,还是经验不足,要多敲敲代码了