一、上传原理与配置
1.1 原理
将客户端文件上传到服务器端,再将服务器端的文件(临时文件)移动到指定目录即可。
1.2 客户端配置
所需:表单页面(选择上传文件);
具体而言:发送方式为POST
,添加enctype="multipart/form-data"
属性,两者缺一不可(但是,优缺点并存,这里也限定了上传的方式和上传的文件之后的调用等方面,后面会说到
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
< html >
< head >
< meta http-equiv = "Content-Type" content = "text/html; charset=UTF-8" >
< title >Insert title here</ title >
</ head >
< body >
< form action = "doAction.php" method = "post" enctype = "multipart/form-data" >
请选择您要上传的文件:
< input type = "file" name = "myFile" />< br />
< input type = "submit" value = "上传" />
</ form >
<? php
?>
</ body >
</ html >
|
先是表单页面(请自动忽略前端问题。。。),关键就是form的属性;另外就是input 中用到了type="file"这一点(体现到php的强大的拓展等等)。
然后是doAction.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
40
41
42
|
<?php
$filename = $_FILES [ 'myFile' ][ 'name' ];
$type = $_FILES [ 'myFile' ][ 'type' ];
$tmp_name = $_FILES [ 'myFile' ][ 'tmp_name' ];
$size = $_FILES [ 'myFile' ][ 'size' ];
$error = $_FILES [ 'myFile' ][ 'error' ];
copy ( $tmp_name , "copies/" . $filename );
move_uploaded_file( $tmp_name , "uploads/" . $filename );
if ( $error ==0) {
echo "上传成功!" ;
} else {
switch ( $error ){
case 1:
echo "超过了上传文件的最大值,请上传2M以下文件" ;
break ;
case 2:
echo "上传文件过多,请一次上传20个及以下文件!" ;
break ;
case 3:
echo "文件并未完全上传,请再次尝试!" ;
break ;
case 4:
echo "未选择上传文件!" ;
break ;
case 5:
echo "上传文件为0" ;
break ;
}
}
|
先把print_r($_FILES)
这个信息看一下
1
2
3
4
5
6
7
8
9
10
11
12
|
Array
(
[myFile] => Array
(
[name] => 梁博_简历.doc
[type] => application/msword
[tmp_name] => D:\wamp\tmp\php1D78.tmp
[error] => 0
[size] => 75776
)
)
|
所以得到的是个二维数组,该怎么用,都是基本的东西(其实我喜欢降维再用);
基本是一眼就懂的东西,不罗嗦,关键有两个:tmp_name
临时文件名;error
报错信息(代号,后面可以利用);
然后这里看一下doAction后面一部分,利用报错信息来反馈给用户,需要说明的是为什么报错,和报错信息是什么都
1.3 关于报错
--报错原因
基本上都是超过或者不符合服务器关于上传文件的配置,那么服务器端配置有哪些呢?
先考虑上传我们用了什么?POST,upload
所以在php.ini中找这么几项:
file_upload
:On
upload_tmp_dir
=——临时文件保存目录;
upload_max_filesize
=2M
max_file_uploads
=20——允许一次上传的最大文件数量(注意和上面那个的区别,有没有size,别乱想)
post_max_size
=8M——post方式发送数据的最大值
其他相关配置
max_exectuion_time
=-1——最大执行时间,避免程序不好占用服务器资源;
max_input_time
=60
max_input_nesting_level
=64——输入嵌套深度;
memory_limit
=128M——最大单线程的独立内存使用量
总之都是有关资源的配置。
--错误号
UPLOAD_ERR_OK
值:0; 没有错误发生,文件上传成功。
UPLOAD_ERR_INI_SIZE
值:1; 上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。
UPLOAD_ERR_FORM_SIZE
值:2; 上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。
UPLOAD_ERR_PARTIAL
值:3; 文件只有部分被上传。
UPLOAD_ERR_NO_FILE
值:4; 没有文件被上传。
注意:这个错误信息是第一步上传的信息,也就是上传到临时文件夹的情况,而不是move或者copy的情况。
二、上传相关限制
2.1 客户端限制
1
2
3
4
5
6
|
<form action= "doAction2.php" method= "post" enctype= "multipart/form-data" >
<input type= "hidden" name= "MAX_FILE_SIZE" value= "101321" />
请选择您要上传的文件:
<input type= "file" name= "myFile" accept= "image/jpeg,image/gif,text/html" /><br/>
<input type= "submit" value= "上传" />
</form>
|
这里用input的属性对上传文件的大小和类型进行了限制,但是个人感觉:一,html代码是“可见的”;二,常不起作用(没找到原因,但因为第一个我也想放弃它,知道就好。
2.2 服务器端限制
主要限制大小和类型,再有就是方式。
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
|
<?php
header( 'content-type:text/html;charset=utf-8' );
$fileinfo = $_FILES [ "myFile" ];
$filename = $fileinfo [ "name" ];
$tmp_name = $fileinfo [ "tmp_name" ];
$size = $fileinfo [ "size" ];
$error = $fileinfo [ "error" ];
$type = $fileinfo [ "type" ];
$maxsize =10485760;
$allowExt = array ( 'jpeg' , 'jpg' , 'png' , 'gif' );
$ext = pathinfo ( $filename ,PATHINFO_EXTENSION);
$path = "uploads" ;
if (! file_exists ( $path )) {
mkdir ( $path ,0777,true);
chmod ( $path , 0777);
}
$uniName =md5(uniqid(microtime(true),true)). $ext ;
if ( $error ==0) {
if ( $size > $maxsize ) {
exit ( "上传文件过大!" );
}
if (!in_array( $ext , $allowExt )) {
exit ( "非法文件类型" );
}
if (! is_uploaded_file ( $tmp_name )) {
exit ( "上传方式有误,请使用post方式" );
}
if (@move_uploaded_file( $tmp_name , $uniName )) {
echo "文件" . $filename . "上传成功!" ;
} else {
echo "文件" . $filename . "上传失败!" ;
}
if (! getimagesize ( $tmp_name )) {
exit ( "不是真正的图片类型" );
}
} else {
switch ( $error ){
case 1:
echo "超过了上传文件的最大值,请上传2M以下文件" ;
break ;
case 2:
echo "上传文件过多,请一次上传20个及以下文件!" ;
break ;
case 3:
echo "文件并未完全上传,请再次尝试!" ;
break ;
case 4:
echo "未选择上传文件!" ;
break ;
case 7:
echo "没有临时文件夹" ;
break ;
}
}
|
2.3 封装
函数
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
|
<?php
function uploadFile( $fileInfo , $path , $allowExt , $maxSize ){
$filename = $fileInfo [ "name" ];
$tmp_name = $fileInfo [ "tmp_name" ];
$size = $fileInfo [ "size" ];
$error = $fileInfo [ "error" ];
$type = $fileInfo [ "type" ];
$ext = pathinfo ( $filename ,PATHINFO_EXTENSION);
if (! file_exists ( $path )) {
mkdir ( $path ,0777,true);
chmod ( $path , 0777);
}
$uniName =md5(uniqid(microtime(true),true)). '.' . $ext ;
$destination = $path . "/" . $uniName ;
if ( $error ==0) {
if ( $size > $maxSize ) {
exit ( "上传文件过大!" );
}
if (!in_array( $ext , $allowExt )) {
exit ( "非法文件类型" );
}
if (! is_uploaded_file ( $tmp_name )) {
exit ( "上传方式有误,请使用post方式" );
}
if (! getimagesize ( $tmp_name )) {
exit ( "不是真正的图片类型" );
}
if (@move_uploaded_file( $tmp_name , $destination )) {
echo "文件" . $filename . "上传成功!" ;
} else {
echo "文件" . $filename . "上传失败!" ;
}
} else {
switch ( $error ){
case 1:
echo "超过了上传文件的最大值,请上传2M以下文件" ;
break ;
case 2:
echo "上传文件过多,请一次上传20个及以下文件!" ;
break ;
case 3:
echo "文件并未完全上传,请再次尝试!" ;
break ;
case 4:
echo "未选择上传文件!" ;
break ;
case 7:
echo "没有临时文件夹" ;
break ;
}
}
return $destination ;
}
|
调用
1
2
3
4
5
6
7
8
|
<?php
header( 'content-type:text/html;charset=utf-8' );
$fileInfo = $_FILES [ "myFile" ];
$maxSize =10485760;
$allowExt = array ( 'jpeg' , 'jpg' , 'png' , 'tif' );
$path = "uploads" ;
include_once 'upFunc.php' ;
uploadFile( $fileInfo , $path , $allowExt , $maxSize );
|
三、多文件的上传实现
3.1 利用单文件封装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
<html>
<head>
<meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" >
<title>Insert title here</title>
</head>
<body>
<form action= "doAction5.php" method= "post" enctype= "multipart/form-data" >
请选择您要上传的文件:<input type= "file" name= "myFile1" /><br/>
请选择您要上传的文件:<input type= "file" name= "myFile2" /><br/>
请选择您要上传的文件:<input type= "file" name= "myFile3" /><br/>
请选择您要上传的文件:<input type= "file" name= "myFile4" /><br/>
<input type= "submit" value= "上传" />
</form>
</body>
</html>
|
1
2
3
4
5
6
7
|
<?php
header( 'content-type:text/html;charset=utf-8' );
include_once 'upFunc.php' ;
foreach ( $_FILES as $fileInfo ){
$file []=uploadFile( $fileInfo );
}
|
这里的思路,从print_r($_FILES)
中去找,打印出来看到是个二维数组,很简单,遍历去用就好了!
上面那个function的定义改一下,给定一些默认值
1
|
function uploadFile( $fileInfo , $path = "uploads" , $allowExt = array ( 'jpeg' , 'jpg' , 'png' , 'tif' ), $maxSize =10485760){
|
这样子,简单是简单,但遇到一些问题。
正常的上传4个图片是没问题,但要是中间激活了函数中的exit,就会立即停止,导致其他图片也无法上传。
3.2升级版封装
旨在实现针对多个或单个文件上传的封装
首先这样子写个静态文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
<html>
<head>
<meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" >
<title>Insert title here</title>
</head>
<body>
<form action= "doAction5.php" method= "post" enctype= "multipart/form-data" >
请选择您要上传的文件:<input type= "file" name= "myFile[]" /><br/>
请选择您要上传的文件:<input type= "file" name= "myFile[]" /><br/>
请选择您要上传的文件:<input type= "file" name= "myFile[]" /><br/>
请选择您要上传的文件:<input type= "file" name= "myFile[]" /><br/>
<input type= "submit" value= "上传" />
</form>
</body>
</html>
|
打印一下$_FILES
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
|
Array
(
[myFile] => Array
(
[name] => Array
(
[0] => test32.png
[1] => test32.png
[2] => 333.png
[3] => test41.png
)
[type] => Array
(
[0] => image/png
[1] => image/png
[2] => image/png
[3] => image/png
)
[tmp_name] => Array
(
[0] => D:\wamp\tmp\php831C.tmp
[1] => D:\wamp\tmp\php834C.tmp
[2] => D:\wamp\tmp\php837C.tmp
[3] => D:\wamp\tmp\php83BB.tmp
)
[error] => Array
(
[0] => 0
[1] => 0
[2] => 0
[3] => 0
)
[size] => Array
(
[0] => 46174
[1] => 46174
[2] => 34196
[3] => 38514
)
)
)
|
可以得到一个三维数组。
复杂是复杂了,但复杂的有规律,各项数值都在一起了,很方便我们取值!!
所以先得到文件信息,变成单文件处理那种信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
function getFiles(){
$i =0;
foreach ( $_FILES as $file ){
if ( is_string ( $file [ 'name' ])){
$files [ $i ]= $file ;
$i ++;
} elseif ( is_array ( $file [ 'name' ])){
foreach ( $file [ 'name' ] as $key => $val ){
$files [ $i ][ 'name' ]= $file [ 'name' ][ $key ];
$files [ $i ][ 'type' ]= $file [ 'type' ][ $key ];
$files [ $i ][ 'tmp_name' ]= $file [ 'tmp_name' ][ $key ];
$files [ $i ][ 'error' ]= $file [ 'error' ][ $key ];
$files [ $i ][ 'size' ]= $file [ 'size' ][ $key ];
$i ++;
}
}
}
return $files ;
}
|
然后之前的那种exit错误,就把exit改一下就好了,这里用res
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
|
function uploadFile( $fileInfo , $path = './uploads' , $flag =true, $maxSize =1048576, $allowExt = array ( 'jpeg' , 'jpg' , 'png' , 'gif' )){
$res = array ();
if ( $fileInfo [ 'error' ]===UPLOAD_ERR_OK){
if ( $fileInfo [ 'size' ]> $maxSize ){
$res [ 'mes' ]= $fileInfo [ 'name' ]. '上传文件过大' ;
}
$ext =getExt( $fileInfo [ 'name' ]);
if (!in_array( $ext , $allowExt )){
$res [ 'mes' ]= $fileInfo [ 'name' ]. '非法文件类型' ;
}
if ( $flag ){
if (! getimagesize ( $fileInfo [ 'tmp_name' ])){
$res [ 'mes' ]= $fileInfo [ 'name' ]. '不是真实图片类型' ;
}
}
if (! is_uploaded_file ( $fileInfo [ 'tmp_name' ])){
$res [ 'mes' ]= $fileInfo [ 'name' ]. '文件不是通过HTTP POST方式上传上来的' ;
}
if ( $res ) return $res ;
if (! file_exists ( $path )){
mkdir ( $path ,0777,true);
chmod ( $path ,0777);
}
$uniName =getUniName();
$destination = $path . '/' . $uniName . '.' . $ext ;
if (!move_uploaded_file( $fileInfo [ 'tmp_name' ], $destination )){
$res [ 'mes' ]= $fileInfo [ 'name' ]. '文件移动失败' ;
}
$res [ 'mes' ]= $fileInfo [ 'name' ]. '上传成功' ;
$res [ 'dest' ]= $destination ;
return $res ;
} else {
switch ( $fileInfo [ 'error' ]) {
case 1 :
$res [ 'mes' ] = '上传文件超过了PHP配置文件中upload_max_filesize选项的值' ;
break ;
case 2 :
$res [ 'mes' ] = '超过了表单MAX_FILE_SIZE限制的大小' ;
break ;
case 3 :
$res [ 'mes' ] = '文件部分被上传' ;
break ;
case 4 :
$res [ 'mes' ] = '没有选择上传文件' ;
break ;
case 6 :
$res [ 'mes' ] = '没有找到临时目录' ;
break ;
case 7 :
case 8 :
$res [ 'mes' ] = '系统错误' ;
break ;
}
return $res ;
}
}
|
里面封装两个小的
1
2
3
4
5
6
7
8
9
10
11
|
function getExt( $filename ){
return strtolower ( pathinfo ( $filename ,PATHINFO_EXTENSION));
}
function getUniName(){
return md5(uniqid(microtime(true),true));
}
|
然后在静态中,使用multiple属性实现多个文件的输入
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
<html>
<head>
<meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" >
<title>Insert title here</title>
</head>
<body>
<form action= "doAction6.php" method= "POST" enctype= "multipart/form-data" >
请选择您要上传的文件:<input type= "file" name= "myFile[]" multiple= 'multiple' /><br/>
<input type= "submit" value= "上传" />
</form>
</body>
</html>
|
doAction6.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<?php
header( "content-type:text/html;charset=utf-8" );
require_once 'upFunc2.php' ;
require_once 'common.func.php' ;
$files =getFiles();
foreach ( $files as $fileInfo ){
$res =uploadFile( $fileInfo );
echo $res [ 'mes' ], '<br/>' ;
$uploadFiles []=@ $res [ 'dest' ];
}
$uploadFiles = array_values ( array_filter ( $uploadFiles ));
|
四、面向对象的文件上传
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
|
<?php
class upload{
protected $fileName ;
protected $maxSize ;
protected $allowMime ;
protected $allowExt ;
protected $uploadPath ;
protected $imgFlag ;
protected $fileInfo ;
protected $error ;
protected $ext ;
public function __construct( $fileName = 'myFile' , $uploadPath = './uploads' , $imgFlag =true, $maxSize =5242880, $allowExt = array ( 'jpeg' , 'jpg' , 'png' , 'gif' ), $allowMime = array ( 'image/jpeg' , 'image/png' , 'image/gif' )){
$this ->fileName= $fileName ;
$this ->maxSize= $maxSize ;
$this ->allowMime= $allowMime ;
$this ->allowExt= $allowExt ;
$this ->uploadPath= $uploadPath ;
$this ->imgFlag= $imgFlag ;
$this ->fileInfo= $_FILES [ $this ->fileName];
}
protected function checkError(){
if (! is_null ( $this ->fileInfo)){
if ( $this ->fileInfo[ 'error' ]>0){
switch ( $this ->fileInfo[ 'error' ]){
case 1:
$this ->error= '超过了PHP配置文件中upload_max_filesize选项的值' ;
break ;
case 2:
$this ->error= '超过了表单中MAX_FILE_SIZE设置的值' ;
break ;
case 3:
$this ->error= '文件部分被上传' ;
break ;
case 4:
$this ->error= '没有选择上传文件' ;
break ;
case 6:
$this ->error= '没有找到临时目录' ;
break ;
case 7:
$this ->error= '文件不可写' ;
break ;
case 8:
$this ->error= '由于PHP的扩展程序中断文件上传' ;
break ;
}
return false;
} else {
return true;
}
} else {
$this ->error= '文件上传出错' ;
return false;
}
}
protected function checkSize(){
if ( $this ->fileInfo[ 'size' ]> $this ->maxSize){
$this ->error= '上传文件过大' ;
return false;
}
return true;
}
protected function checkExt(){
$this ->ext= strtolower ( pathinfo ( $this ->fileInfo[ 'name' ],PATHINFO_EXTENSION));
if (!in_array( $this ->ext, $this ->allowExt)){
$this ->error= '不允许的扩展名' ;
return false;
}
return true;
}
protected function checkMime(){
if (!in_array( $this ->fileInfo[ 'type' ], $this ->allowMime)){
$this ->error= '不允许的文件类型' ;
return false;
}
return true;
}
protected function checkTrueImg(){
if ( $this ->imgFlag){
if (!@ getimagesize ( $this ->fileInfo[ 'tmp_name' ])){
$this ->error= '不是真实图片' ;
return false;
}
return true;
}
}
protected function checkHTTPPost(){
if (! is_uploaded_file ( $this ->fileInfo[ 'tmp_name' ])){
$this ->error= '文件不是通过HTTP POST方式上传上来的' ;
return false;
}
return true;
}
protected function showError(){
exit ( '<span style="color:red">' . $this ->error. '</span>' );
}
protected function checkUploadPath(){
if (! file_exists ( $this ->uploadPath)){
mkdir ( $this ->uploadPath,0777,true);
}
}
protected function getUniName(){
return md5(uniqid(microtime(true),true));
}
public function uploadFile(){
if ( $this ->checkError()&& $this ->checkSize()&& $this ->checkExt()&& $this ->checkMime()&& $this ->checkTrueImg()&& $this ->checkHTTPPost()){
$this ->checkUploadPath();
$this ->uniName= $this ->getUniName();
$this ->destination= $this ->uploadPath. '/' . $this ->uniName. '.' . $this ->ext;
if (@move_uploaded_file( $this ->fileInfo[ 'tmp_name' ], $this ->destination)){
return $this ->destination;
} else {
$this ->error= '文件移动失败' ;
$this ->showError();
}
} else {
$this ->showError();
}
}
}
|
1
2
3
4
5
6
|
<?php
header( 'content-type:text/html;charset=utf-8' );
require_once 'upload.class.php' ;
$upload = new upload( 'myFile1' , 'imooc' );
$dest = $upload ->uploadFile();
echo $dest ;
|
五、下载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
<html xmlns= "http://www.w3.org/1999/xhtml" >
<head>
<meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" />
<title>Insert title here</title>
</head>
<body>
<a href= "1.rar" >下载1.rar</a>
<br />
<a href= "1.jpg" >下载1.jpg</a>
<br />
<a href= "doDownload.php?filename=1.jpg" >通过程序下载1.jpg</a>
<br />
<a href= "doDownload.php?filename=../upload/nv.jpg" >下载nv.jpg</a>
<?php
?>
</body>
</html>
|
1
2
3
4
5
6
|
<?php
$filename = $_GET [ 'filename' ];
header('content-disposition:attachment;
filename='. basename ( $filename ));
header( 'content-length:' . filesize ( $filename ));
readfile( $filename );
|
总结:
<form action="doAction.php" method="post" enctype="multipart/form-data">
<input type="file" name="myFile" /><br/>
二维数组的降维处理;
$_FILES变量
move_upload_file();copy();
tmp_name临时文件;
拓展名的提取;
真实图片的验证;
唯一文件名的生成;
函数封装以及调用;
利用单个文件函数实现多文件上传;
小功能的封装;
多文件的遍历;
面向对象的开发过程;
本文转至 https://www.php.cn/php-weizijiaocheng-429549.html PHP中文网