PHP实现文件上传下载实例详细讲解

PHP实现文件上传下载实例详细讲解

内容导读

收集整理的这篇技术教程文章主要介绍了PHP实现文件上传下载实例详细讲解,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含16996字,纯文字阅读大概需要25分钟

内容图文

一、上传原理与配置

1.1 原理

将客户端文件上传到服务器端,再将服务器端的文件(临时文件)移动到指定目录即可。

1.2 客户端配置

所需:表单页面(选择上传文件);

具体而言:发送方式为POST,添加enctype="multipart/form-data"属性,两者缺一不可(但是,优缺点并存,这里也限定了上传的方式和上传的文件之后的调用等方面,后面会说到

<!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

<?php//$_FILES:文件上传变量//print_r($_FILES);$filename=$_FILES['myFile']['name'];$type=$_FILES['myFile']['type'];$tmp_name=$_FILES['myFile']['tmp_name'];$size=$_FILES['myFile']['size'];$error=$_FILES['myFile']['error'];//将服务器上的临时文件移动到指定位置//方法一move_upload_file($tmp_name,$destination)//move_uploaded_file($tmp_name, "uploads/".$filename);//文件夹应提前建立好,不然报错//方法二copy($src,$des)//以上两个函数都是成功返回真,否则返回false//copy($tmp_name, "copies/".$filename);//注意,不能两个方法都对临时文件进行操作,临时文件似乎操作完就没了,我们试试反过来copy($tmp_name, "copies/".$filename);move_uploaded_file($tmp_name, "uploads/".$filename);//能够实现,说明move那个函数基本上相当于剪切;copy就是copy,临时文件还在//另外,错误信息也是不一样的,遇到错误可以查看或者直接报告给用户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)这个信息看一下

Array(

[myFile] => Array



(





[name] => 梁博_简历.doc





[type] => application/msword





[tmp_name] => D:wamptmpphp1D78.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 客户端限制

<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 服务器端限制

主要限制大小和类型,再有就是方式。

<?phpheader('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;//10M,10*1024*1024$allowExt=array('jpeg','jpg','png','gif');//允许上传的文件类型(拓展名$ext=pathinfo($filename,PATHINFO_EXTENSION);//提取上传文件的拓展名//目的信息$path="uploads";if (!file_exists($path)) {
 //当目录不存在,就创建目录

mkdir($path,0777,true);

chmod($path, 0777);}//$destination=$path."/".$filename;//得到唯一的文件名!防止因为文件名相同而产生覆盖$uniName=md5(uniqid(microtime(true),true)).$ext;//md5加密,uniqid产生唯一id,microtime做前缀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)) {//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 封装

函数

<?phpfunction 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)) {//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;}

调用

<?phpheader('content-type:text/html;charset=utf-8');$fileInfo=$_FILES["myFile"];$maxSize=10485760;//10M,10*1024*1024$allowExt=array('jpeg','jpg','png','tif');$path="uploads";include_once 'upFunc.php';uploadFile($fileInfo, $path, $allowExt, $maxSize);

三、多文件的上传实现

3.1 利用单文件封装

<!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>
<?php//print_r($_FILES);header('content-type:text/html;charset=utf-8');include_once 'upFunc.php';foreach ($_FILES as $fileInfo){

$file[]=uploadFile($fileInfo);}

这里的思路,从print_r($_FILES)中去找,打印出来看到是个二维数组,很简单,遍历去用就好了!

上面那个function的定义改一下,给定一些默认值

function uploadFile($fileInfo,$path="uploads",$allowExt=array('jpeg','jpg','png','tif'),$maxSize=10485760){

这样子,简单是简单,但遇到一些问题。

正常的上传4个图片是没问题,但要是中间激活了函数中的exit,就会立即停止,导致其他图片也无法上传。

3.2升级版封装

旨在实现针对多个或单个文件上传的封装

首先这样子写个静态文件

<!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

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:wamptmpphp831C.tmp









[1] => D:wamptmpphp834C.tmp









[2] => D:wamptmpphp837C.tmp









[3] => D:wamptmpphp83BB.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属性实现多个文件的输入

<!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

<?php //print_r($_FILES);header("content-type:text/html;charset=utf-8");require_once 'upFunc2.php';require_once 'common.func.php';$files=getFiles();// print_r($files);foreach($files as $fileInfo){

$res=uploadFile($fileInfo);

echo $res['mes'],'<br/>';

$uploadFiles[]=@$res['dest'];}$uploadFiles=array_values(array_filter($uploadFiles));//print_r($uploadFiles);

四、面向对象的文件上传

<?php class upload{

protected $fileName;

protected $maxSize;

protected $allowMime;

protected $allowExt;

protected $uploadPath;

protected $imgFlag;

protected $fileInfo;

protected $error;

protected $ext;

/**

 * @param string $fileName

 * @param string $uploadPath

 * @param string $imgFlag

 * @param number $maxSize

 * @param array $allowExt

 * @param array $allowMime

 */

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];

}

/**

 * 检测上传文件是否出错

 * @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('<span style="color:red">'.$this->error.'</span>');

}

/**

 * 检测目录不存在则创建

 */

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();



}

}}
<?php header('content-type:text/html;charset=utf-8');require_once 'upload.class.php';$upload=new upload('myFile1','imooc');$dest=$upload->uploadFile();echo $dest;

五、下载

<!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>
<?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临时文件;

拓展名的提取;

真实图片的验证;

唯一文件名的生成;

函数封装以及调用;

利用单个文件函数实现多文件上传;

小功能的封装;

多文件的遍历;

面向对象的开发过程;

下载;

以上就是全部的讲解,希望可以帮助到大家,有错误的地方请指出。

更多相关问题请访问PHP中文网:PHP视频教程

以上就是PHP实现文件上传下载实例详细讲解的详细内容,更多请关注Gxl网其它相关文章!

内容总结

以上是为您收集整理的PHP实现文件上传下载实例详细讲解全部内容,希望文章能够帮你解决PHP实现文件上传下载实例详细讲解所遇到的程序开发问题。 如果觉得技术教程内容还不错,欢迎将网站推荐给程序员好友。

内容备注

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。


本文关键词:

联系我们

在线咨询:点击这里给我发消息

邮件:w420220301@qq.com