微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

一个经典的PHP文件上传类分享

<div class="jb51code">文件上传是项目开发中比较常见的功能,但文件上传的过程比较繁琐,只要是有文件上传的地方就需要编写这些复杂的代码。为了能在每次开发中降低功能的编写难度,也为了能节省开发时间,通常我们都会将这些反复使用的一段代码封装到一个类中。帮助开发者在以后的开发中,通过编写几条简单代码就可以实现复杂的文件上传功能。对于基础薄弱的读者,只要会使用本类即可,而对一些喜欢挑战的朋友,可以尝试去读懂它,并能开发一个属于自己的文件上传类。

一、需求分析

  要球自定义文件上传类,即在使用非常简便的前提下,又可以完成以下几项功能:   ①支持单个文件上传。   ②支持多个文件上传。   ③可以自己指定上传文件的保存位置,可以设置上传文件允许的大小和类型,可以由系统对上传文件重新命名,又可以设置保留上传文件的原名。   (说明:要求单个文件上传和多个文件上传要采用同样的操作方式,对上传进行的一些设置也要采用相同的方式)。

二、程序设计

  根据程序需求的要求,我们可以为文件上传类声明4个可见的成员属性,让用户在使用时还可以进行一些行为的设置。需要的成员属性如下表所示:

  为避免属性的值被赋上一些非法值,需要将这些成员属性封装起来,在对象外面不能访问,再通过类中声明的set()方法为以上四个成员属性赋值。set()方法有两个参数,第一个参数就是成员属性名称(不区分大小写),第二个参数,就是前面参数中属性对应的值。set()方法调用完成以后,返回本对象($this),所以除了可以单独为每个属性赋值以外,还可以进行连贯操作一起为多个属性赋值。本例中除了set()方法以外,最主要的是实现上传文件功能,所以系统主要提供了以下一些公有方法,实现文件上传的操作,如下表所示:

 为避免属性的值被赋上一些非法值,需要将这些成员属性封装起来,在对象外面不能访问,再通过类中声明的set()方法为以上四个成员属性赋值。set()方法有两个参数,第一个参数就是成员属性名称(不区分大小写),第二个参数,就是前面参数中属性对应的值。set()方法调用完成以后,返回本对象($this),所以除了可以单独为每个属性赋值以外,还可以进行连贯操作一起为多个属性赋值。本例中除了set()方法以外,最主要的是实现上传文件功能,所以系统主要提供了以下一些公有方法,实现文件上传的操作,如下表所示:

rush:PHP;"> 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->s<a href="https://www.jb51.cc/tag/eto/" target="_blank" class="keywords">eto</a>ption($key,$val); } return $this; } /** * <a href="https://www.jb51.cc/tag/diaoyong/" target="_blank" class="keywords">调用</a>该<a href="https://www.jb51.cc/tag/fangfa/" target="_blank" class="keywords">方法</a><a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a><a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a> * @p<a href="https://www.jb51.cc/tag/ara/" target="_blank" class="keywords">ara</a>m string $fileFile <a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a><a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>的表单<a href="https://www.jb51.cc/tag/mingcheng/" target="_blank" class="keywords">名称</a> * @return bool 如果<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>成功返回数true */ function upload($fileField) { $return = true; /* <a href="https://www.jb51.cc/tag/jianchawenjian/" target="_blank" class="keywords">检查文件</a>路径是滞合法 */ if( !$this->checkFilePath() ) { $this->errorMess = $this->getError(); return false; } /* 将<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a><a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>的信息取出赋给变量 */ $name = $_FILES[$fileField]['name']; $tmp_name = $_FILES[$fileField]['tmp_name']; $size = $_FILES[$fileField]['size']; $error = $_FILES[$fileField]['error']; /* 如果是多个<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a><a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>则$file["name"]会是<a href="https://www.jb51.cc/tag/yige/" target="_blank" class="keywords">一个</a>数组 */ if(is_Array($name)){ $errors=array(); /*多个<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a><a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>则循环处理 , 这个循环只有检查<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a><a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>的作用,并没有真正<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a> */ 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; } /* 如果有问题,则重新初使化<a href="https://www.jb51.cc/tag/shuxing/" target="_blank" class="keywords">属性</a> */ if(!$return) $this->setFiles(); } if($return){ /* 存放所有<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>后<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>名的变量数组 */ $fileNames = array(); /* 如果<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>的多个<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>都是合法的,则通过销魂循环向服务器<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a><a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a> */ for($i = 0; $i < count($name); $i++){ if($this->setFiles($name[$i],$error[$i] )) { $this->setNewFileName(); if(!$this-><a href="https://www.jb51.cc/tag/cop/" target="_blank" class="keywords">cop</a>yFile()){ $errors[] = $this->getError(); $return = false; } $fileNames[] = $this->newFileName; } } $this->newFileName = $fileNames; } $this->errorMess = $errors; return $return; /*<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>单个<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>处理<a href="https://www.jb51.cc/tag/fangfa/" target="_blank" class="keywords">方法</a>*/ } else { /* 设置<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>信息 */ if($this->setFiles($name,$tmp_name,$size,$error)) { /* <a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>之前先检查一下大小和类型 */ if($this->checkFileSize() && $this->checkFileType()){ /* 为<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a><a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>设置新<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>名 */ $this->setNewFileName(); /* <a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a><a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a> 返回0为成功, 小于0都为<a href="https://www.jb51.cc/tag/cuowu/" target="_blank" class="keywords">错误</a> */ if($this-><a href="https://www.jb51.cc/tag/cop/" target="_blank" class="keywords">cop</a>yFile()){ return true; }else{ $return=false; } }else{ $return=false; } } else { $return=false; } //如果$return为false,则出错,将<a href="https://www.jb51.cc/tag/cuowu/" target="_blank" class="keywords">错误</a>信息保存在<a href="https://www.jb51.cc/tag/shuxing/" target="_blank" class="keywords">属性</a>errorMess中 if(!$return) $this->errorMess=$this->getError(); return $return; } } /** * <a href="https://www.jb51.cc/tag/huoqu/" target="_blank" class="keywords">获取</a><a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>后的<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a><a href="https://www.jb51.cc/tag/mingcheng/" target="_blank" class="keywords">名称</a> * @p<a href="https://www.jb51.cc/tag/ara/" target="_blank" class="keywords">ara</a>m void 没有参数 * @return string <a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>后,新<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>的<a href="https://www.jb51.cc/tag/mingcheng/" target="_blank" class="keywords">名称</a>, 如果是多<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a><a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>返回数组 */ public function getFileName(){ return $this->newFileName; } /** * <a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>失败后,<a href="https://www.jb51.cc/tag/diaoyong/" target="_blank" class="keywords">调用</a>该<a href="https://www.jb51.cc/tag/fangfa/" target="_blank" class="keywords">方法</a>则返回,<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>出错信息 * @p<a href="https://www.jb51.cc/tag/ara/" target="_blank" class="keywords">ara</a>m void 没有参数 * @return string 返回<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a><a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>出错的信息报告,如果是多<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a><a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>返回数组 */ public function getErrorMsg(){ return $this->errorMess; } /* 设置<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>出错信息 */ private function getError() { $str = "<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a><a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a><font color='red'>{$this->originName}</font>时出错 : "; switch ($this->errorNum) { case 4: $str .= "没有<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>被<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>"; break; case 3: $str .= "<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>只有部分被<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>"; break; case 2: $str .= "<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a><a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>的大小超过了HTML表单中MAX_FILE_SIZE选项指定的值"; break; case 1: $str .= "<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>的<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>超过了<a href="https://www.jb51.cc/tag/PHP/" target="_blank" class="keywords">PHP</a>.ini中upload_max_filesize选项限制的值"; break; case -1: $str .= "未允许类型"; break; case -2: $str .= "<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>过大,<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>的<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>不能超过{$this->maxsize}个字节"; break; case -3: $str .= "<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>失败"; break; case -4: $str .= "建立存放<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a><a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>目录失败,请重新指定<a href="https://www.jb51.cc/tag/shangchuanmulu/" target="_blank" class="keywords">上传目录</a>"; break; case -5: $str .= "必须指定<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a><a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>的路径"; break; default: $str .= "未知<a href="https://www.jb51.cc/tag/cuowu/" target="_blank" class="keywords">错误</a>"; } return $str.'<br>'; } /* 设置和$_FILES有关的<a href="https://www.jb51.cc/tag/neirong/" target="_blank" class="keywords">内容</a> */ private function setFiles($name="",$tmp_name="",$size=0,$error=0) { $this->s<a href="https://www.jb51.cc/tag/eto/" target="_blank" class="keywords">eto</a>ption('errorNum',$error); if($error) return false; $this->s<a href="https://www.jb51.cc/tag/eto/" target="_blank" class="keywords">eto</a>ption('originName',$name); $this->s<a href="https://www.jb51.cc/tag/eto/" target="_blank" class="keywords">eto</a>ption('tmpFileName',$tmp_name); $aryStr = explode(".",$name); $this->s<a href="https://www.jb51.cc/tag/eto/" target="_blank" class="keywords">eto</a>ption('fileType',strtolower($aryStr[count($aryStr)-1])); $this->s<a href="https://www.jb51.cc/tag/eto/" target="_blank" class="keywords">eto</a>ption('fileSize',$size); return true; } /* 为单个成员<a href="https://www.jb51.cc/tag/shuxing/" target="_blank" class="keywords">属性</a>设置值 */ private function s<a href="https://www.jb51.cc/tag/eto/" target="_blank" class="keywords">eto</a>ption($key,$val) { $this->$key = $val; } /* 设置<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>后的<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a><a href="https://www.jb51.cc/tag/mingcheng/" target="_blank" class="keywords">名称</a> */ private function setNewFileName() { if ($this->israndname) { $this->s<a href="https://www.jb51.cc/tag/eto/" target="_blank" class="keywords">eto</a>ption('newFileName',$this->proRandName()); } else{ $this->s<a href="https://www.jb51.cc/tag/eto/" target="_blank" class="keywords">eto</a>ption('newFileName',$this->originName); } } /* 检查<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>的<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>是否是合法的类型 */ private function checkFileType() { if (in_array(strtolower($this->fileType),$this->allowtype)) { return true; }else { $this->s<a href="https://www.jb51.cc/tag/eto/" target="_blank" class="keywords">eto</a>ption('errorNum',-1); return false; } } /* 检查<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>的<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>是否是允许的大小 */ private function checkFileSize() { if ($this->fileSize > $this->maxsize) { $this->s<a href="https://www.jb51.cc/tag/eto/" target="_blank" class="keywords">eto</a>ption('errorNum',-2); return false; }else{ return true; } } /* 检查是否有存放<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a><a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>的目录 */ private function checkFilePath() { if(empty($this->path)){ $this->s<a href="https://www.jb51.cc/tag/eto/" target="_blank" class="keywords">eto</a>ption('errorNum',-5); return false; } if (!file_exists($this->path) || !is_writable($this->path)) { if (!@mkdir($this->path,0755)) { $this->s<a href="https://www.jb51.cc/tag/eto/" target="_blank" class="keywords">eto</a>ption('errorNum',-4); return false; } } return true; } /* 设置<a href="https://www.jb51.cc/tag/suiji/" target="_blank" class="keywords">随机</a><a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>名 */ private function proRandName() { $fileName = date('YmdHis')."_".rand(100,999); return $fileName.'.'.$this->fileType; } /* 复制<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a><a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>到指定的位置 */ private function <a href="https://www.jb51.cc/tag/cop/" target="_blank" class="keywords">cop</a>yFile() { if(!$this->errorNum) { $path = rtrim($this->path,'/').'/'; $path .= $this->newFileName; if (@move_uploaded_file($this->tmpFileName,$path)) { return true; }else{ $this->s<a href="https://www.jb51.cc/tag/eto/" target="_blank" class="keywords">eto</a>ption('errorNum',-3); return false; } } else { return false; } }

}

四、文件上传类的应用过程

  本例的文件上传类FileUpload,即支持文件上传,也支持多个文件一起向服务器上传,在处理方式上没有区别的,只不过在编写上传标单时,多个文件上传一定要以数组方式传递给服务器。单个文件上传表单如下所示:

rush:PHP;">
name:
up pic: up pic: up pic: up pic:

  上面表单,都将提交的位置指向了同一个文件upload.PHP,所以不难看出单个和多个文件上传是一样的处理方式,upload.PHP代码如下所示:

rush:PHP;"> $up = new fileupload;
//设置属性(上传的位置, 大小, 类型, 名是是否要随机生成)
$up -> set("path","./images/");
$up -> set("maxsize",2000000);
$up -> set("allowtype",array("gif","png","jpg","jpeg"));
$up -> set("israndname",false);

//使用对象中的upload方法, 就可以上传文件方法需要传一个上传表单的名子 pic,如果成功返回true,失败返回false
if($up -> upload("pic")) {
echo '

';
//获取上传文件名子
var_dump($up->getFileName());
echo '
';

} else {
echo '

';
//获取上传失败以后的错误提示
var_dump($up->getErrorMsg());
echo '
';
}
?>

  在upload.PHP文件中,首先必须加载文件上传FileUpload类所在的文件fileupload.class.PHP。再就是实例化文件上传类的对象,然后通过调用upload()方法上传文件,如果上传成功,可以通过getFileName()方法获取上传后的文件名称,如果上传失败,还可以通过getErrorMsg()方法获取错误报告。如果需要改变上传的一些行为,可以通过调用set()方法来完成一些属性的设置。set()方法可以单独使用设置一个属性的值,如果需要改变多个属性的值,可以连续调用set()方法进行设置,也可以连贯操作同时设置多个属性

下载PHP文件上传类:

文件上传类.rar

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

相关推荐