本文介绍了php实现文件上传与下载,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧。
一、上传原理与配置
1.1 原理
将客户端文件上传到服务器端,再将服务器端的文件(临时文件)移动到指定目录即可。
1.2 客户端配置
所需:表单页面(选择上传文件);
具体而言:发送方式为post,添加enctype=multipart/form-data属性,两者缺一不可(但是,优缺点并存,这里也限定了上传的方式和上传的文件之后的调用等方面,后面会说到)
insert title here请选择您要上传的文件:
先是表单页面(请自动忽略前端问题。。。),关键就是form的属性;另外就是input 中用到了type=file这一点(体现到php的强大的拓展等等)。
然后是doaction
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——最大单线程的独立内存使用量
总之都是有关资源的配置。
--错误号
以下(偷懒)引自http://blog.sina.com.cn/s/blog_3cdfaea201008utf.html
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 客户端限制
请选择您要上传的文件:
这里用input的属性对上传文件的大小和类型进行了限制,但是个人感觉:一,html代码是“可见的”;二,常不起作用(没找到原因,但因为第一个我也想放弃它,知道就好。
2.2 服务器端限制
主要限制大小和类型,再有就是方式。
$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)) {//getimagesize真实返回数组,否则返回false 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 封装
函数
$maxsize) { exit(上传文件过大!); } if (!in_array($ext, $allowext)) { exit(非法文件类型); } if (!is_uploaded_file($tmp_name)) { exit(上传方式有误,请使用post方式); } //判断是否为真实图片(防止伪装成图片的病毒一类的 if (!getimagesize($tmp_name)) {//getimagesize真实返回数组,否则返回false 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;}
调用
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 ) ))
可以得到一个三维数组。
复杂是复杂了,但复杂的有规律,各项数值都在一起了,很方便我们取值!!
所以先得到文件信息,变成单文件处理那种信息
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){ //我的天,这个$key用的diao $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
function uploadfile($fileinfo,$path='./uploads',$flag=true,$maxsize=1048576,$allowext=array('jpeg','jpg','png','gif')){ //$flag=true; //$allowext=array('jpeg','jpg','gif','png'); //$maxsize=1048576;//1m //判断错误号 $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'].'不是真实图片类型'; } } //检测文件是否是通过http post上传上来的 if(!is_uploaded_file($fileinfo['tmp_name'])){ $res['mes']=$fileinfo['name'].'文件不是通过http post方式上传上来的'; } if($res) return $res; //$path='./uploads'; 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; }}
里面封装了两个小的
function getext($filename){ return strtolower(pathinfo($filename,pathinfo_extension));}/** * 产生唯一字符串 * @return string */function getuniname(){ return md5(uniqid(microtime(true),true));}
然后静态中,用multiple属性实现多个文件的输入;
insert title here请选择您要上传的文件:
doaction6maxsize=$maxsize; $this->allowmime=$allowmime; $this->allowext=$allowext; $this->uploadpath=$uploadpath; $this->imgflag=$imgflag; $this->fileinfo=$_files[$this->filename]; } /** * 检测上传文件是否出错 * @return boolean */ 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; } } /** * 检测上传文件的大小 * @return boolean */ protected function checksize(){ if($this->fileinfo['size']>$this->maxsize){ $this->error='上传文件过大'; return false; } return true; } /** * 检测扩展名 * @return boolean */ 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; } /** * 检测文件的类型 * @return boolean */ protected function checkmime(){ if(!in_array($this->fileinfo['type'],$this->allowmime)){ $this->error='不允许的文件类型'; return false; } return true; } /** * 检测是否是真实图片 * @return boolean */ protected function checktrueimg(){ if($this->imgflag){ if(!@getimagesize($this->fileinfo['tmp_name'])){ $this->error='不是真实图片'; return false; } return true; } } /** * 检测是否通过http post方式上传上来的 * @return boolean */ protected function checkhttppost(){ if(!is_uploaded_file($this->fileinfo['tmp_name'])){ $this->error='文件不是通过http post方式上传上来的'; return false; } return true; } /** *显示错误 */ protected function showerror(){ exit(''.$this->error.''); } /** * 检测目录不存在则创建 */ protected function checkuploadpath(){ if(!file_exists($this->uploadpath)){ mkdir($this->uploadpath,0777,true); } } /** * 产生唯一字符串 * @return string */ protected function getuniname(){ return md5(uniqid(microtime(true),true)); } /** * 上传文件 * @return string */ 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(); } }}uploadfile();echo $dest;
四、下载
对于浏览器不识别的,可以直接下载,但对于能识别的,需要多一两步
insert title here下载1.rar
下载1.jpg
通过程序下载1.jpg
下载nv.jpg<?php $filename=$_get['filename'];header('content-disposition:attachment;filename='.basename($filename));header('content-length:'.filesize($filename));readfile($filename);
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!