仅为实现一个简单的上传环境,不提供普适参考。
1. 环境
安装apache和php环境:
apt-get install apache2
apt-get install apache2-mpm-prefork \
php5-cli \
php5-common \
php5-curl \
php5-ldap \
php5-mysql \
php5-sqlite \
php5-xsl \
libapache2-mod-php5
1.1 服务端配置
- file_uploads = On,支持HTTP上传
- upload_tmp_dir=,临时文件保存目录
- upload_max_filesize=2M,允许上传文件的最大值
- max_file_uploads=20,允许一次上传的最大文件数
- post_max_size=8M,POST方式发送数据的最大值
1.2 错误信息说明
- 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,文件只有部分被上传
2. 业务
2.1 上传页面
这里我直接修改了apache的默认页面:
/var/www/index.html
1 <html>
2 <head>
3 <meta charset="utf-8"/>
4 <title>文件上传表单</title>
5 </head>
6 <body>
7 <table>
8 <form enctype='multipart/form-data' name='myform' action='submit.php' method='post'>
9 <input type="hidden" name="MAX_FILE_SIZE" value="1000000000"/>
10 <tr><td>选择文件上传
11 <input name='rzfile' type='file'/>
12 </td></tr>
13 <tr><td colspan='2'>
14 <input name='submit' value='上传' type='submit'/>
15 </td></tr>
16 </form>
17 </table>
18 </body>
19 </html>
2.2 上传处理
submit.php:
1 <?php
2 //header('content-type:test/html;charset=utf-8');
3 //1.通过$_FILES文件上传变量接收上传文件信息
4 print_r($_FILES);
5 $file=$_FILES['rzfile'];
6 $filename=$file['name'];
7 $type=$file['type'];
8 $tmp_name=$file['tmp_name'];
9 $size=$file['size'];
10 $error=$file['error'];
11
12 $uploaddir='/upload/';
13 $uploadfile=$uploaddir.basename($filename);
14
15 //2.判断错误号,只有为0或者是UPLOAD_ERR_OK,表示没有错误发生,上传成功
16 if($error == UPLOAD_ERR_OK) {
17 if(move_uploaded_file($tmp_name, $uploadfile)) {
18 echo 'file:'.$filename.'upload successful';
19 }
20 else {
21 echo 'file'.$filename.'upload failed';
22 }
23 }else{
24 switch($error) {
25 case 1:
26 echo '1: upload file size beyond upload_max_filesize';
27 break;
28 case 2:
29 echo '2: upload file size beyond post form MAX_FILE_SIZE limit';
30 break;
31 case 3:
32 echo '3: 文件被部分上传';
33 break;
34 case 4:
35 echo '4: 没有选择上传文件';
36 break;
37 case 6:
38 echo '6: 没有找到临时目录';
39 break;
40 case 7:
41 case 8:
42 echo '7:8: 系统错误';
43 break;
44 }
45 }
46 ?>
注意
submit.php将接收到的暂存在/tmp文件夹下的临时文件移动到新的目录,这个目录需要开放写权限,例如我mkdir生成的/upload目录:
drwxrwxrwx 2 root root 4096 Jun 22 17:51 upload
3. php文件上传原理
表单设置为post方式,enctype设置为multipart/form-data,既通过post表单发送到服务端缓存目录。
服务端通过$_FILES获取上传文件信息,对其进行转移。
3.1 $_FILES
上传文件变量。
- name:上传文件名称
- type:上传文件类型
- tmp_name:临时文件名
- size:上传文件大小
- error:错误码
通过$_FILES获得临时文件名,通过move_uploaded_file()函数将其移动到一个具有写权限的目录中永久保存。
4. 抓包解析流程
wireshark抓到网关与上传服务器的交互流程,一下为其http body部分:
POST /submit.php HTTP/1.0\r\n
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarygtzbr1BiPtIx1ok6\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n
Content-Length: 1163338\r\n
Content-Type项中multipart/form-data可判断客户端采用multipart格式传递信息,
boundary可分析出分隔符特征
Content-Length是啥呢?
网友评论