PHP文件系统处理
文件系统概述
文件类型
文件的属性
目录的基本操作
解析目录路径
1
2
3
4
5
|
<?php $path = "D:/amp/php/php.ini" ; echo basename ( $path ). "<br/>" ; //php.ini echo basename ( $path , ".ini" ). "<br/>" ; //php echo basename ( $path , ".php" ); //php.ini |
1
2
3
|
<?php $path = "D:/amp/php/php.ini" ; echo dirname( $path ). "<br/>" ; // D:/amp/php |
1
2
3
4
5
6
|
<?php $path = "D:/amp/php/php.ini" ; $path_parts = pathinfo ( $path ); echo $path_parts [ 'dirname' ]. "<br/>" ; //D:/amp/php echo $path_parts [ 'basename' ]. "<br/>" ; //php.ini echo $path_parts [ 'extension' ]. "<br/>" ; //i |
遍历目录
opendir()
倒回目录句柄,接受已经用opendir()函数打开的可操作目录句柄作为参数。将目录指针重置到目录开始处,即倒回目录的开头。
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
|
<?php date_default_timezone_set( "PRC" ); $num = 0; //用来统计子目录和文件的个数 $dirname = 'd:/amp/php' ; //保存当前目录下用来遍历的一个目录名 $dir_handle = opendir( $dirname ); //用opendir打开目录 //将遍历的目录和文件名使用表格格式输出 echo '<table border="0" align="center" width="600" cellspacing="0" cellpadding="0">' ; echo '<caption><h2>目录' . $dirname . '下面的内容</h2></caption>' ; echo '<tr align="left" bgcolor="#cccccc">' ; echo '<th>文件名</th><th>文件大小</th><th>文件类型</th><th>修改时间</th></tr>' ; //使用readdir循环读取目录里的内容 while ( $file = readdir( $dir_handle )) { //将目录下的文件和当前目录连接起来,才能在程序中使用 $dirFile = $dirname . "/" . $file ; $bgcolor = $num ++%2==0 ? '#FFFFFF' : '#CCCCCC' ; //隔行一种颜色 echo '<tr bgcolor=' . $bgcolor . '>' ; echo '<td>' . $file . '</td>' ; //显示文件名 echo '<td>' . filesize ( $dirFile ). '</td>' ; //显示文件大小 echo '<td>' . filetype ( $dirFile ). '</td>' ; //显示文件类型 echo '<td>' . date ( "Y/n/t" , filemtime ( $dirFile )). '</td>' ; //格式化显示文件修改时间 echo '</tr>' ; } echo '</table>' ; //关闭表格标记 closedir ( $dir_handle ); //关闭文件操作句柄 echo '在<b>' . $dirname . '</b>目录下的子目录和文件共有<b>' . $num . '</b>个' ; |
统计目录大小
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
|
<?php /** 自定义一个函数dirSize(),统计传入参数的目录大小 @param string $directory 目录名称 @return double 目录的尺寸大小 */ function dirSize( $directory ) { $dir_size = 0; //用来累加各个文件大小 if ( $dir_handle = @opendir( $directory )) { //打开目录,并判断是否能成功打开 while ( $filename = readdir( $dir_handle ) ) { //循环遍历目录下的所有文件 if ( $filename != "." && $filename != ".." ) { //一定要排除两个特殊的目录 $subFile = $directory . "/" . $filename ; //将目录下的子文件和当前目录相连 if ( is_dir ( $subFile )) //如果为目录 $dir_size += dirSize( $subFile ); //递归地调用自身函数,求子目录的大小 if ( is_file ( $subFile )) //如果是文件 $dir_size += filesize ( $subFile ); //求出文件的大小并累加 } } closedir ( $dir_handle ); //关闭文件资源 return $dir_size ; //返回计算后的目录大小 } } $dir_size = dirSize( "d:/amp/php" ); //调用该函数计算目录大小 echo round ( $dir_size /pow(1024,1),2). "KB" ; //字节数转换为“KB”单位并输出 |
建立和删除目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<?php /** 自定义函数递归的删除整个目录 @param string $directory 目录名称 */ function delDir( $directory ) { if ( file_exists ( $directory )) { //如果不存在rmdir()函数会出错 if ( $dir_handle = @opendir( $directory )) { //打开目录并判断是否成功 while ( $filename = readdir( $dir_handle )) { //循环遍历目录 if ( $filename != "." && $filename != ".." ) { //一定要排除两个特殊的目录 $subFile = $directory . "/" . $filename ; //将目录下的文件和当前目录相连 if ( is_dir ( $subFile )) //如果是目录条件则成立 delDir( $subFile ); //递归调用自己删除子目录 if ( is_file ( $subFile )) //如果是文件条件则成立 unlink( $subFile ); //直接删除这个文件 } } closedir ( $dir_handle ); //关闭目录资源 rmdir ( $directory ); //删除空目录 } } } delDir( "phpMyAdmin" ); //调用delDir()函数,将程序所在目录中的“phpMyAdmin”文件夹删除 |
复制目录
首先对源目录进行遍历,如果遇到的是普通文件,直接使用copy进行赋值;如果遍历时遇到一个目录,则必须建立该目录,然后再对该目录下的文件进行复制操作,如果还有子目录,则使用递归重复操作,最终将整个目录复制完成。
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
|
<?php /** 自定义函数递归的复制带有多级子目录的目录 @param string $dirSrc 原目录名称字符串 @param string $dirTo 目标目录名称字符串 */ function copyDir( $dirSrc , $dirTo ) { if ( is_file ( $dirTo )) { //如果目标不是一个目录则退出 echo "目标不是目录不能创建!!" ; return ; //退出函数 } if (! file_exists ( $dirTo )) { //如果目标目录不存在则创建 mkdir ( $dirTo ); //创建目录 } if ( $dir_handle = @opendir( $dirSrc )) { //打开目录并判断是否成功 while ( $filename = readdir( $dir_handle )) { //循环遍历目录 if ( $filename != "." && $filename != ".." ) { //一定要排除两个特殊的目录 $subSrcFile = $dirSrc . "/" . $filename ; //将源目录的多级子目录连接 $subToFile = $dirTo . "/" . $filename ; //将目标目录的多级子目录连接 if ( is_dir ( $subSrcFile )) //如果源文件是一个目录 copyDir( $subSrcFile , $subToFile ); //递归调用自己复制子目录 if ( is_file ( $subSrcFile )) //如果源文件是一个普通文件 copy ( $subSrcFile , $subToFile ); //直接复制到目标位置 } } closedir ( $dir_handle ); //关闭目录资源 } } //测试函数,将目录"phpMyAdmin"复制到"D:/admin" copyDir( "phpMyAdmin" , "D:/admin" ); |
文件的基本操作
文件的打开与关闭
fopen()建立与文件资源的连接,fclose()关闭通过fopen函数打开的文件资源。
fopen()
- 第一个参数:需要被打开的文件URL。
- 第二个参数:文件操作模式
- 第三个参数是可选的,如果资源位于本地系统,php则认为可以使用本地路径或是相对路径来访问此资源。如果将这个参数设置为1,就会是php考虑配置指令include_path中指定的路径(在php的配置该文件中设置)。
- 第四个参数也是可选的。fopen()函数允许文件名称以协议名称开始。例如"http://"并且在一个远程位置打开该文件。通过设置这个参数,还可以支持一些其他的协议。
写入文件
- 第一个参数:需要打开的文件资源。
- 第二个参数:需要输入的字符串内容。
- 第三个参数:可选。将在输入length个字符串时停止。
1
2
3
4
5
6
7
8
9
10
11
|
<?php //声明一个变量用来保存文件名 $filename = "d:\\data.txt" ; //使用fopen()函数以只写的模式打开文件,如果不存在则创建它,打开失败则通过程序 $handle = fopen ( $filename , "w" ) or die ( "打开文件失败!" ); //写入文件 for ( $i = 0; $i < 10; $i ++){ fwrite( $handle , $i . "写啊写!\r\n" ); } //关闭打开的文件资源 fclose( $handle ); |
读取文件内容
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
|
<?php header( "ContentType:text/html;charset:utf8" ); //从文件中读取制定字节数的内容存入到一个变量中 $filename = "d:\\data.txt" ; $handle = fopen ( $filename , "r" ) or die ( "文件打开失败!" ); $contents = fread ( $handle , 100); fclose( $handle ); echo $contents . "<hr/>" ; //从文件中读取全部内容存入到一个变量中,每次读取一部分,循环读取 $filename = "d:\\01.jpg" ; $handle = fopen ( $filename , "rb" ) or die ( "文件打开失败!" ); $contents = "" ; while (! feof ( $handle )){ $contents .= fread ( $handle , 1024); } fclose( $handle ); echo $contents . "<hr/>" ; //另一种从文件中读取全部内容的方法 $filename = "d:\\data.txt" ; $handle = fopen ( $filename , "r" ) or die ( "文件打开失败!" ); $contents - fread ( $handle , filesize ( $filename )); fclose( $handle ); echo $contents ; |
1
2
3
4
5
6
7
|
<?php $handle = fopen ( "d:\\data.txt" , "r" ) or die ( "文件打开失败!" ); while (! feof ( $handle )){ $buffer = fgets ( $handle , 4096); echo $buffer . "<br/>" ; } fclose( $handle ); |
1
2
3
4
5
6
|
<?php $handle = fopen ( "d:\\data.txt" , "r" ) or die ( "文件打开失败!" ); while (false !== ( $char = fgetc ( $handle ))){ echo $char . "<br/>" ; } fclose( $handle ); |
1
2
|
<?php readfile( "d:\\data.txt" ); |
远程访问文件
移动文件指针
- SEEK_CUR:设置指针位置为当前位置加上第二个参数所提供的offset字节。
- SEEK_END:设置指针位置为EOF加上offset字节。在这里,offset必须设置为负值。
- SEEK_SET:设置指针位置为offset字节处。这与忽略第三个参数whence效果相同。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<?php //以只读模式打开文件 $fp = fopen ( 'data.txt' , 'r' ) or die ( "文件打开失败" ); echo ftell ( $fp ). "<br>" ; //输出刚打开文件的指针默认位置,指针在文件的开头位置为0 echo fread ( $fp , 10). "<br>" ; //读取文件中的前10个字符输出,指针位置发生了变化 echo ftell ( $fp ). "<br>" ; //读取文件的前10个字符之后,指针移动的位置在第10个字节处 fseek ( $fp , 100, SEEK_CUR); //将文件指针的位置,由当前位置向后移动100个字节数 echo ftell ( $fp ). "<br>" ; //文件位置在110个字节处 echo fread ( $fp , 10). "<br>" ; //读取110到120字节数位置的字符串,读取后指针的位置为120 fseek ( $fp , -10, SEEK_END); //又将指针移动到倒数10个字节位置处 echo fread ( $fp , 10). "<br>" ; //输出文件中最后10个字符 rewind ( $fp ); //又移动文件指针到文件的开头 echo ftell ( $fp ). "<br>" ; //指针在文件的开头位置,输出0 fclose( $fp ); //关闭文件资源 |
移动文件指针到文件的开头。
文件的所定机制
flock()
可以对文件使用锁定机制(锁定或释放文件)。当一个进程早访问文件时加上锁,其他进程要想对该文件进行访问,必须等到锁定被释放以后。这样避免在兵法访问同一个文件时破坏数据。
第一个参数:一个已经打开的文件资源。
第二个参数:规定使用哪种锁定类型。值为以下:
- LOCK_SH取得共享锁定(从文件中读取数据时使用)。
- LOCK_EX取得独占锁定(像文件中写入数据时使用)。
- LOCK_UN释放锁定(无论何种锁定,均由此释放)。
- LOCK_NB附加锁定(如果不希望flock()在锁定时堵塞,则应在上述锁定后加上此锁)。
如果锁定会堵塞的话(已经被flock()锁定的文件,再次锁定时,flock()函数会被挂起,这时成为锁定堵塞),也可以将可选的第三个参数设置为1,则当进行锁定时会阻塞其他进程。锁定操作也可以被fclose()释放。为了让flock()函数发挥作用,在所有访问文件的程序中都必须使用相同的锁定文件。该函数如果成功则返回true,失败则返回false。
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
|
<html> <head><title>网络留言板模式</title></head> <body> <?php //声明一个变量保存文件名,在这个文件中保存留言信息 $filename = "text_data.txt" ; //判断用户是否按下提交按钮,用户提交后则条件成功 if (isset( $_POST [ "sub" ])){ //接收表单中三条内容,并整合为一条,使用“||”分隔,使用“<|>”结尾 $message = $_POST [ "username" ]. "||" . $_POST [ "title" ]. "||" . $_POST [ "mess" ]. "<|>" ; writeMessage( $filename , $message ); //调用自定义函数,将信息写入文件 } if ( file_exists ( $filename )) //判断文件是否存在,如果存在则条件成立 readMessage( $filename ); //文件存在则调用自定义函数,读取数据 /** 自定义一个向文件中写入数据的函数 @param string $filename 写入的文件名 @param string $message 写入文件的内容,即消息 */ function writeMessage( $filename , $message ) { $fp = fopen ( $filename , "a" ); //以追加模式打开文件 if ( flock ( $fp , LOCK_EX)) { //进行排他型锁定(独占锁定) fwrite( $fp , $message ); //将数据写入文件 flock ( $fp , LOCK_UN); //同样使用flock()函数释放锁定 } else { //如果建立独占锁定失败 echo "不能锁定文件!" ; //输出错误消息 } fclose( $fp ); //关闭文件资源 } /** 自定义一个遍历读取文件的函数 @param string $filename 读取的文件名 */ function readMessage( $filename ){ $fp = fopen ( $filename , "r" ); //以只读的模式打开文件 flock ( $fp , LOCK_SH); //建立文件的共享锁定 $buffer = "" ; //将文件中的数据遍历后放入这个字符串中 while (! feof ( $fp )) { //使用while循环将文件中数据遍历出来 $buffer .= fread ( $fp , 1024); //读出数据追加到$buffer变量中 } $data = explode ( "<|>" , $buffer ); //通过“<|>”将每行留言分隔并存入到数组中 foreach ( $data as $line ) { //遍历数组将每行数据以HTML输出 //将每行数据再分隔 list( $username , $title , $message )= explode ( "||" , $line ); //判断每部分是否为空 if ( $username != "" && $title != "" && $message != "" ) { echo $username . '说:' ; //输出用户名 echo ' ' . $title . ',' ; //输出标题 echo $message . "<hr>" ; //输出留言主题信息 } } flock ( $fp , LOCK_UN); //释放锁定 fclose( $fp ); //关闭文件资源 } ?> <!-- 以下为用户输入表单界面(GUI)--> <form action= "" method= "post" > 用户名:<input type= "text" size=10 name= "username" ><br> 标 题:<input type= "text" size=30 name= "title" ><br> <textarea name= "mess" rows=4 cols=38>请在这里输入留言信息!</textarea> <input type= "submit" name= "sub" value= "留言" > </form> </body> </html> |
文件的一些基本操作函数
文件的上传与下载
文件上传
客户端上传设置
如果支持文件上传操作,必须在<form>标签中将enctype和method两个属性指明相应的值。
- enctype="multipart/form-data"用来指定表单编码数据方式,让服务器知道,我们要传递一个文件,并带有常规的表单信息。
- method="POST"用来致命发送数据的方法。
另外,还需要在form表单中设置一个hidden类型的input框。其中name的值为MAX_FILE_SIZE的隐藏值域,并通过设置其VALUE的值限制上传文件的大小(单位字节),但这个值不能超过PHP的配置文件中upload_max_filesize值设置的大小。
1
2
3
4
5
|
<form action= "upload.php" method= "post" enctype= "multipart/form-data" > <input type= "hidden" name= "MAX_FILE_SIZE" value= "1000000" > 选择文件:<input type= "file" name= "myfile" > <input type= "submit" value= "上传文件" > </form> |
在服务端通过php处理上传
要想通过PHP成功地管理文件上传,需要通过以下三方面信息:
- 设置PHP配置文件中的指令:用于精细地调节PHP的文件上传功能。
- $_FILES多维数组:用于存储各种与上传文件有关信息,其他数据还使用$_POST去接收。
- PHP的文件上传处理函数:用于上传文件的后续处理。
文件上传与PHP配置文件的设置有关,首先,应该设置php.ini文件中的一些指令,精细调节PHP的文件上传功能。在PHP配置文件php.ini中和上传文件有关的指令如下表:
除了上述,还有两个专门用于文件上传所使用的is_uploaded_file()和move_uploaded_file()两个函数。
is_uploaded_file()
判断指定的文件是否是通过HTTP POST上传的,如果是返回true。用于防止潜在的攻击者对原本不能通过脚本交互的文件进行非法管理,这可以用来确保恶意的用户无法欺骗脚本去访问本不能访问的文件。
move_uploaded_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
|
<?php $allowtype = array ( "gif" , "png" , "jpg" ); //设置充许上传的类型为gif, png和jpg $size = 1000000; //设置充许大小为1M(1000000字节)以内的文件 $path = "./uploads" ; //设置上传后保存文件的路径 //判断文件是否可以成功上传到服务器,$_FILES['myfile']['error'] 为0表示上传成功 if ( $_FILES [ 'myfile' ][ 'error' ] > 0) { echo '上传错误: ' ; switch ( $_FILES [ 'myfile' ][ 'error' ]) { case 1: die ( '上传文件大小超出了PHP配置文件中的约定值:upload_max_filesize' ); case 2: die ( '上传文件大小超出了表单中的约定值:MAX_FILE_SIZE' ); case 3: die ( '文件只被部分上载' ); case 4: die ( '没有上传任何文件' ); default : die ( '末知错误' ); } } //判断上传的文件是否为充许的文件类型,通过文件的后缀名 $hz = array_pop ( explode ( "." , $_FILES [ 'myfile' ][ 'name' ])); //通过判断文件的后缀方式,来决定文件是否是充许上传的文件类型 if (!in_array( $hz , $allowtype )) { die ( "这个后缀是<b>{$hz}</b>,不是充许的文件类型!" ); } /* 也可以通过获取上传文件的MIME类型中的主类型和子类型,来限制文件上传的类型 list($maintype,$subtype)=explode("/",$_FILES['myfile']['type']); if ($maintype=="text") { //通过主类型限制不能上传文本文件,例如.txt .html .php等文件 die('问题: 不能上传文本文件。'); } */ //判断上传的文件是否为充许大小 if ( $_FILES [ 'myfile' ][ 'size' ] > $size ) { die ( "超过了充许的<b>{$size}</b>字节大小" ); } //为了系统安全,也为了同名文件不会被覆盖,上传后将文件名使用系统定义 $filename = date ( "YmdHis" ).rand(100,999). "." . $hz ; //判断是否为上传文件 if ( is_uploaded_file ( $_FILES [ 'myfile' ][ 'tmp_name' ])) { if (!move_uploaded_file( $_FILES [ 'myfile' ][ 'tmp_name' ], $path . '/' . $filename )) { die ( '问题: 不能将文件移动到指定目录。' ); } } else { die ( "问题: 上传文件{$_FILES['myfile']['name']}不是一个合法文件: " ); } //如果文件上传成功则输出 echo "文件{$upfile}上传成功,保存在目录{$path}中,大小为{$_FILES['myfile']['size']}字节" ; |
文件下载
PHP使用header()函数发送网页的头部信息给浏览器,该函数接受一个头信息的字符串作为参数。文件下载需要发送的头信息包括以下三部分,通过调用三次header()函数完成,在使用readfile()函数将文件内容读取出来并直接输出。
1
2
3
4
5
6
7
8
9
|
<?php $filename = "test.gif" ; header( 'Content-Type: image/gif' ); //指定下载文件类型 header( 'Content-Disposition: attachment; filename="' . $filename . '"' ); //指定下载文件的描述 header( 'Content-Length: ' . filesize ( $filename )); //指定下载文件的大小 //将文件内容读取出来并直接输出,以便下载 readfile( $filename ); |
文件上传类:
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
|
<?php /** file: fileupload.class.php 文件上传类FileUpload 本类的实例对象用于处理上传文件,可以上传一个文件,也可同时处理多个文件上传 */ class FileUpload { private $path = "./uploads" ; //上传文件保存的路径 private $allowtype = array ( 'jpg' , 'gif' , 'png' ); //设置限制上传文件的类型 private $maxsize = 1000000; //限制文件上传大小(字节) private $israndname = true; //设置是否随机重命名文件, false不随机 private $originName ; //源文件名 private $tmpFileName ; //临时文件名 private $fileType ; //文件类型(文件后缀) private $fileSize ; //文件大小 private $newFileName ; //新文件名 private $errorNum = 0; //错误号 private $errorMess = "" ; //错误报告消息 /** * 用于设置成员属性($path, $allowtype,$maxsize, $israndname) * 可以通过连贯操作一次设置多个属性值 *@param string $key 成员属性名(不区分大小写) *@param mixed $val 为成员属性设置的值 *@return object 返回自己对象$this,可以用于连贯操作 */ function set( $key , $val ){ $key = strtolower ( $key ); if ( array_key_exists ( $key , get_class_vars(get_class( $this ) ) ) ){ $this ->setOption( $key , $val ); } return $this ; } /** * 调用该方法上传文件 * @param string $fileFile 上传文件的表单名称 * @return bool 如果上传成功返回数true */ function upload( $fileField ) { $return = true; /* 检查文件路径是滞合法 */ if ( ! $this ->checkFilePath() ) { $this ->errorMess = $this ->getError(); return false; } /* 将文件上传的信息取出赋给变量 */ $name = $_FILES [ $fileField ][ 'name' ]; $tmp_name = $_FILES [ $fileField ][ 'tmp_name' ]; $size = $_FILES [ $fileField ][ 'size' ]; $error = $_FILES [ $fileField ][ 'error' ]; /* 如果是多个文件上传则$file["name"]会是一个数组 */ if ( is_Array ( $name )){ $errors = array (); /*多个文件上传则循环处理 , 这个循环只有检查上传文件的作用,并没有真正上传 */ for ( $i = 0; $i < count ( $name ); $i ++){ /*设置文件信息 */ if ( $this ->setFiles( $name [ $i ], $tmp_name [ $i ], $size [ $i ], $error [ $i ] )) { if (! $this ->checkFileSize() || ! $this ->checkFileType()){ $errors [] = $this ->getError(); $return =false; } } else { $errors [] = $this ->getError(); $return =false; } /* 如果有问题,则重新初使化属性 */ if (! $return ) $this ->setFiles(); } if ( $return ){ /* 存放所有上传后文件名的变量数组 */ $fileNames = array (); /* 如果上传的多个文件都是合法的,则通过销魂循环向服务器上传文件 */ for ( $i = 0; $i < count ( $name ); $i ++){ if ( $this ->setFiles( $name [ $i ], $tmp_name [ $i ], $size [ $i ], $error [ $i ] )) { $this ->setNewFileName(); if (! $this ->copyFile()){ $errors [] = $this ->getError(); $return = false; } $fileNames [] = $this ->newFileName; } } $this ->newFileName = $fileNames ; } $this ->errorMess = $errors ; return $return ; /*上传单个文件处理方法*/ } else { /* 设置文件信息 */ if ( $this ->setFiles( $name , $tmp_name , $size , $error )) { /* 上传之前先检查一下大小和类型 */ if ( $this ->checkFileSize() && $this ->checkFileType()){ /* 为上传文件设置新文件名 */ $this ->setNewFileName(); /* 上传文件 返回0为成功, 小于0都为错误 */ if ( $this ->copyFile()){ return true; } else { $return =false; } } else { $return =false; } } else { $return =false; } //如果$return为false, 则出错,将错误信息保存在属性errorMess中 if (! $return ) $this ->errorMess= $this ->getError(); return $return ; } } /** * 获取上传后的文件名称 * @param void 没有参数 * @return string 上传后,新文件的名称, 如果是多文件上传返回数组 */ public function getFileName(){ return $this ->newFileName; } /** * 上传失败后,调用该方法则返回,上传出错信息 * @param void 没有参数 * @return string 返回上传文件出错的信息报告,如果是多文件上传返回数组 */ public function getErrorMsg(){ return $this ->errorMess; } /* 设置上传出错信息 */ private function getError() { $str = "上传文件<font color='red'>{$this->originName}</font>时出错 : " ; switch ( $this ->errorNum) { case 4: $str .= "没有文件被上传" ; break ; case 3: $str .= "文件只有部分被上传" ; break ; case 2: $str .= "上传文件的大小超过了HTML表单中MAX_FILE_SIZE选项指定的值" ; break ; case 1: $str .= "上传的文件超过了php.ini中upload_max_filesize选项限制的值" ; break ; case -1: $str .= "未允许类型" ; break ; case -2: $str .= "文件过大,上传的文件不能超过{$this->maxsize}个字节" ; break ; case -3: $str .= "上传失败" ; break ; case -4: $str .= "建立存放上传文件目录失败,请重新指定上传目录" ; break ; case -5: $str .= "必须指定上传文件的路径" ; break ; default : $str .= "未知错误" ; } return $str . '<br>' ; } /* 设置和$_FILES有关的内容 */ private function setFiles( $name = "" , $tmp_name = "" , $size =0, $error =0) { $this ->setOption( 'errorNum' , $error ); if ( $error ) return false; $this ->setOption( 'originName' , $name ); $this ->setOption( 'tmpFileName' , $tmp_name ); $aryStr = explode ( "." , $name ); $this ->setOption( 'fileType' , strtolower ( $aryStr [ count ( $aryStr )-1])); $this ->setOption( 'fileSize' , $size ); return true; } /* 为单个成员属性设置值 */ private function setOption( $key , $val ) { $this -> $key = $val ; } /* 设置上传后的文件名称 */ private function setNewFileName() { if ( $this ->israndname) { $this ->setOption( 'newFileName' , $this ->proRandName()); } else { $this ->setOption( 'newFileName' , $this ->originName); } } /* 检查上传的文件是否是合法的类型 */ private function checkFileType() { if (in_array( strtolower ( $this -> fileType ), $this ->allowtype)) { return true; } else { $this ->setOption( 'errorNum' , -1); return false; } } /* 检查上传的文件是否是允许的大小 */ private function checkFileSize() { if ( $this -> fileSize > $this ->maxsize) { $this ->setOption( 'errorNum' , -2); return false; } else { return true; } } /* 检查是否有存放上传文件的目录 */ private function checkFilePath() { if ( empty ( $this ->path)){ $this ->setOption( 'errorNum' , -5); return false; } if (! file_exists ( $this ->path) || ! is_writable ( $this ->path)) { if (!@ mkdir ( $this ->path, 0755)) { $this ->setOption( 'errorNum' , -4); return false; } } return true; } /* 设置随机文件名 */ private function proRandName() { $fileName = date ( 'YmdHis' ). "_" .rand(100,999); return $fileName . '.' . $this -> fileType ; } /* 复制上传文件到指定的位置 */ private function copyFile() { if (! $this ->errorNum) { $path = rtrim( $this ->path, '/' ). '/' ; $path .= $this ->newFileName; if (@move_uploaded_file( $this ->tmpFileName, $path )) { return true; } else { $this ->setOption( 'errorNum' , -3); return false; } } else { return false; } } } |