单文件上传

原理

  • 文件从用户本地电脑通过web表单传输到服务器指定目录下

流程

  1. 浏览器请求一个服务器html脚本,包含文件上传表单
  2. 用户选择文件并上传
  3. 服务器将文件保存到临时目录
  4. 服务器脚本开始工作,判断文件有效,将有效文件从tmp目录移到指定目录(文件上传完成)

[zd-plane title=“演示图”]

[/zd-plane]

表单制作

表单包含三个属性:

  • method属性:表单必须用post方式
  • enctype属性:form 表单属性,用来规范表单数据的编码方式
  • action属性:将数据提交给哪里

对应的HTML代码

1
2
3
4
<form method='post' enctype='multipart/form-data' action='action.php'>
<input type="file" name="image">
<input type="submit" name="submit" value="提交">
</form>

用户看到上传文件和提交按钮,用户提交后,文件上传到服务器临时文件夹

$_FILES值

超预变量**$_FILES,**用来存储用户上传的文件信息

$_FILES包含以下内容

name :

  • 文件在用户电脑实际名字

tmp_name:

  • 文件上传到服务器后临路径

type:

  • 显示文件类型(不能相信name的后缀!!!!!!)

error:

文件上传的代号告知php文件接收中出现的问题

  • 0 上传成功
  • 1 文件超过了php设置的最大值
  • 2 文件超过html表单最大值
  • 3 只有部分文件被上传,出现网络中断
  • 4 没有文件被上传
  • 6 找不到临时文件
  • 7 php没有权限将临时文件移动到指定目录

size:

  • 文件大小

知道_FILES功能后,创建\_FILES功能后,创建`file=$_FILES[‘image’]` ;获得文件全部信息。使用

$file['tmp_name'] 将得到文件名xxx.jpg

$file['type'] 文件类型

等等函数来移动文件到目标目录

移动临时文件到目标位置

  1. 判断是否为http上传的文件 is_uploaded_file($filename)
  2. 如果满足条件1则移动文件 move_uploaded_file($filename,$destination)
1
2
3
4
5
6
7
8
9
#创建file变量,取得文件
$file=$_FILES['image']; #这里的名字与表单内input 的file类型的 name一样
#判断是否为上传文件
if(is_uploaded_file($file['tmp_name'])){ 
#将文件移动到新位置,获得文件名字$file['name'];
move_uploaded_file($file['tmp_name'],'diretory'.'/'.$file['name']);
}else{
echo '不是上传文件';
}

以上为单文件上传过程

多文件上传

html代码

同名表单

  • 针对一个要表述的内容,但使用不同文件:同名表单

所有上传的文件属于一个数组

1
2
3
4
html代码
<input type="file" name="image[]" />
<input type="file" name="image[]" />
<input type="file" name="image[]" />

则$_FILES中,会包含一个image的数组,里面是name属性和type属性等等 每个属性又包含三个值,分别对应三个文件

[zd-plane title=“结果图片”]

[/zd-plane]

不同名表单

  • 表述不同内容:不同名表单

文件有各自的名字,不属于一个数组

1
2
3
4
html代码
<input type="file" name="head" />
<input type="file" name="body" />
<input type="file" name="footer" />

$_FILES 将包含 三个类分别为head\body\footer,各自包含自己的name,type等属性。

[zd-plane title=“结果图片”]

[/zd-plane]

多文件遍历

不同名表单遍历

1
2
3
4
5
6
7
8
9
10
按表单名字直接遍历
foreach ($_FILES as $file){
if(is_uploaded_file($file['tmp_name'])){
if(move_uploaded_file($file['tmp_name'],'./post_files/'.$file['name'])){
echo '上传成功';
}else{
echo '上传失败';
}
}
}

同名表单遍历

1
2
3
4
5
6
7
8
9
10
11
12
因为name\tepe里面各自包含多个变量,那就直接按索引遍历
for ($i = 0; $i < 3; $i++) {
// code...
$files=$_FILES['image'];
if(is_uploaded_file($files['tmp_name'][$i])){
if(move_uploaded_file($files['tmp_name'][$i],'./post_files/'.$files['name'][$i])){
echo '上传成功';
}else{
echo '上传失败';
}
}
}

文件上传的整完代码

  • 包含检测文件类型,大小,检测病毒等功能

[zd-plane title=“文件上传函数”]

  • 以下是action.php内容

upload_single_file函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<?php
#将上传文件封装成函数
function upload_single_file($file,$allow_type,$path,&$error,$allow_format=[],$max_size=2000000){
if(is_array($file)&&isset($file['error'])){
#判断文件error是否有值
}else{
$error ='文件无效';
return false;
}

// 3、判断保存路径是否有效
if(!is_dir($path)){
$error='路径无效';
return false;
}

// 4、判断文件本身是否有错
switch($file['error']){
case 1:
case 2:
$error='文件超出服务器允许大小';
return false;
case 3:
$error='文件上传过程出现错误';
return false;
case 4:
$error='未选择要上传的文件';
return false;
case 6:
case 7:
$error='文件保存失败';
return false;
}

// 5、判断MIME类型是否允许
if(!in_array($file['type'],$allow_type)){
$error='文件类型不合适';
return false;
}

// 6、判断文件是否过大
if($file['size']>$max_size){
$error='文件过大';
return false;
}

// 7、判断后缀是否允许
$ext=ltrim(strrchr($file['name'],'.'),'.');
if(!empty($allow_format) && !in_array($ext,$allow_format)){
$error='文件后缀不符合!!!只能为jpg,jpeg,png,gif';
return false;
}

// 8、移到指定目录

if(!is_uploaded_file($file['tmp_name'])){
$error='不是上传文件';
return false;
}

// 判断文件是否已经存在
$file_path=$path.'/'.$file['name'];
if(file_exists($file_path)){
$error='文件已经存在';
return false;
}

if(move_uploaded_file($file['tmp_name'],$path.'/'.$file['name'])){
// 检测文件是否有毒
if(check_hex($path,$file['name'])==5){
unlink($path.'/'.$file['name']);
$error='文件可能包含病毒,上传失败';
return false;
}else{
return true;
// return $file['name'];
}

}else{
$error='文件上传失败';
return false;
}


}

$file=$_FILES['image'];
$path='./post_files';
$allow_type=['image/jpg','image/jpeg','image/png','image/gif'];
$allow_format=['jpg','jpeg','png','gif'];
$max_size=20000000;

require './check_hex.php';


if(upload_single_file($file,$allow_type,$path,$error,$allow_format,$max_size)){
// echo $file_name;
echo '上传成功';
}else{
echo $error;
}

check_hex函数,检测图片是否包含一般病毒

  • 以下是check_hex.php内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php
header("Content-type: text/html; charset=utf-8");
function check_hex($path,$img) {
$status = 0;
$tips = array(
"0" => "文件没问题",
"5" => "文件有毒",
"-1" => "文件没有上传"
);
echo '<br/>';
$img=$path.'/'.$img;
if (file_exists($img)) {
$resource = fopen($img, 'rb');
$fileSize = filesize($img);
fseek($resource, 0);
if ($fileSize > 512) { // 取头和尾
$hexCode = bin2hex(fread($resource, 512));
fseek($resource, $fileSize - 512);
$hexCode .= bin2hex(fread($resource, 512));
} else { // 取全部
$hexCode = bin2hex(fread($resource, $fileSize));
}
fclose($resource);
/* 匹配16进制中的 <% ( ) %> */
/* 匹配16进制中的 <? ( ) ?> */
/* 匹配16进制中的 <script | /script> 大小写亦可 */
if (preg_match("/(3c25.*?28.*?29.*?253e)|(3c3f.*?28.*?29.*?3f3e)|(3C534352495054)|(2F5343524950543E)|(3C736372697074)|(2F7363726970743E)/is", $hexCode)) {
$status = 5;
}
} else {
$status = -1;
}
return $status;
}





[/zd-plane]