1 class FileUpload { 2 /** 3 * 文件上传类 4 * @author lhm 5 * for example 6 * $up=new FileUpload(array('israndname'=>true, 7 * 'allowType'=>array('txt', 'doc', 'php', 'gif','jpg'), 8 * 'filepath'=>'./uploads/', 9 * 'maxSize'=>2000000)); 10 * $up->uploadFile('pic');//pic 为文件输入框name值 11 */ 12 private $filepath; //指定上传文件保存的路径 13 private $allowtype=array('gif', 'jpg', 'png', 'jpeg'); //充许上传文件的类型 14 private $maxsize=2000000; //允上传文件的最大长度 2M 15 private $israndname=true; //是否随机重命名, true false不随机,使用原文件名 16 private $originName; //源文件名称 17 private $tmpFileName; //临时文件名 18 private $fileType; //文件类型 19 private $fileSize; //文件大小 20 private $newFileName; //新文件名 21 private $errorNum=0; //错误号 22 private $errorMess=''; //用来提供错误报告 23 24 25 /** 26 * 用于上传文件初始化 27 * 用户可以不用按位置传参数,后面参数给值不用将前几个参数也提供值 28 */ 29 function __construct($options = array()){ 30 $allowOption = array('filepath','allowtype','maxsize','israndname'); 31 foreach($options as $key=>$val){ 32 $key = strtolower($key); 33 //查看用户参数中数组的下标是否和成员属性名相同 34 //if(!in_array($key,get_class_vars(get_class($this)))){ 35 if(!in_array($key, $allowOption)){ 36 $this->setOption('errorNum', 5); 37 $this->errorMess = $this->getError(); 38 continue 1; 39 } 40 $this->setOption($key, $val); 41 } 42 } 43 44 /** 45 * 46 * 用来检查文件上传路径 47 * @access private 48 * @return bool 49 */ 50 private function checkFilePath(){ 51 if(empty($this->filepath)) { 52 $this->setOption('errorNum', -5); 53 return false; 54 } 55 56 if(!file_exists($this->filepath) || !is_writable($this->filepath)){ 57 if(!@mkdir($this->filepath, 0755)){ 58 $this->setOption('errorNum', -4); 59 return false; 60 } 61 } 62 return true; 63 } 64 /** 65 * 66 * 用来检查文件上传的大小 67 * @access private 68 * @return bool 69 */ 70 private function checkFileSize() { 71 if($this->fileSize > $this->maxsize){ 72 $this->setOPtion('errorNum', -2); 73 return false; 74 }else{ 75 return true; 76 } 77 } 78 /** 79 * 80 * 用于检查文件上传类型 81 * @access private 82 * @return bool 83 */ 84 private function checkFileType() { 85 if(in_array(strtolower($this->fileType), $this->allowtype)) { 86 return true; 87 }else{ 88 $this->setOption('errorNum', -1); 89 return false; 90 } 91 } 92 /** 93 * 94 * 检查文件真实上传数量,如果文件名为空,则删除对应元素值 95 * @access private 96 * @param array $name 97 * @param array $tmpName 98 * @param array $size 99 * @param array $error100 * @param array $fileField101 */102 private function checkFileNum($name, $tmpName, $size, $error, $fileField){103 $continue = true;104 for($i=0; $i < count($name); $i++){105 if ($name[$i] === ''){106 $name = $this->deleteArrayElement($name, $i);//线性删除107 $tmpName = $this->deleteArrayElement($tmpName, $i);108 $size = $this->deleteArrayElement($size, $i);109 $error = $this->deleteArrayElement($error, $i);110 $continue = false;111 break 1;112 }113 }114 if ($continue === false){115 $this->checkFileNum($name, $tmpName, $size, $error, $fileField);//递归116 }else {117 //将空空元素删除后重新赋给$_FILES118 $_FILES[$fileField]['name'] = $name;119 $_FILES[$fileField]['tmp_name'] = $tmpName;120 $_FILES[$fileField]['size'] = $size;121 $_FILES[$fileField]['error'] = $error;122 }123 124 }125 /**126 * 127 * 设置上传后的文件名称128 * @access private129 */130 private function setNewFileName(){131 if($this->israndname){132 $this->setOption('newFileName', $this->setRandName());//系统随机名133 } else {134 $this->setOption('newFileName', $this->originName);//沿用文件旧名135 }136 }137 /**138 * 139 * 设置随机文件名称140 * @access private141 * @return string142 */143 private function setRandName(){144 $fileName = date("YmdHis").rand(100,999);145 return $fileName.'.'.$this->fileType;146 }147 /**148 * 149 * 自动生成属性并赋值150 * @param string $key151 * @param string $val152 */153 private function setOption($key, $val){154 $this->$key=$val;155 }156 /**157 * 158 * 用于上传文件159 * @param string $fileField160 */161 public function uploadFile($fileField){162 $return=true;163 //检查初始化是否出错164 if ($this->errorNum != 0){165 $this->errorMess = $this->getError();166 return false;167 }168 //检查文件上传路径169 if(!$this->checkFilePath()){170 $this->errorMess = $this->getError();171 return false;172 }173 174 $this->checkFileNum($_FILES[$fileField]['name'],$_FILES[$fileField]['tmp_name'],175 $_FILES[$fileField]['size'],$_FILES[$fileField]['error'],176 $fileField);177 $name = $_FILES[$fileField]['name'];178 $tmpName = $_FILES[$fileField]['tmp_name'];179 $size = $_FILES[$fileField]['size'];180 $error = $_FILES[$fileField]['error'];181 //print_r($name);182 if(is_Array($name)){183 $errors = array();184 $count = count($name);185 for($i=0; $i < $count; $i++){186 if($this->setFiles($name[$i], $tmpName[$i], $size[$i], $error[$i])){187 if(!$this->checkFileSize() || !$this->checkFileType()){188 $errors[] = $this->getError();189 $return=false;190 }191 }else{192 $error[] = $this->getError();193 $return = false;194 }195 196 if(!$return)197 $this->setFiles();198 }199 200 if($return){201 $fileNames = array();202 for($i = 0; $i < $count; $i++){203 if($this->setFiles($name[$i], $tmpName[$i], $size[$i], $error[$i])){204 $this->setNewFileName();205 if(!$this->copyFile()){206 $errors = $this->getError();207 $return = false;208 }else{209 $fileNames[] = $this->newFileName;210 }211 }212 }213 214 $this->newFileName = $fileNames;215 }216 $this->errorMess = $errors;217 }else{218 if($this->setFiles($name, $tmpName, $size, $error)){219 if($this->checkFileSize() && $this->checkFileType()){220 $this->setNewFileName();221 222 if($this->copyFile()){223 return true;224 }else{225 $return = false;226 }227 228 }else{229 $return = false;230 } 231 }else{232 $return = false;233 }234 235 if(!$return)236 $this->errorMess = $this->getError(); 237 } 238 return $return; 239 }240 /**241 * 242 * 将临时文件移动到正式路径243 * @access private244 * @return bool245 */246 private function copyFile(){247 if(!$this->errorNum){248 $filepath = rtrim($this->filepath, '/').'/';249 $filepath .= $this->newFileName;250 251 if(@move_uploaded_file($this->tmpFileName, $filepath)) {252 return true;253 }else{254 $this->setOption('errorNum', -3);255 return false;256 }257 258 }else{259 return false;260 }261 }262 /**263 * 设置文件属性的值264 */265 private function setFiles($name = '', $tmpName = '', $size = 0, $error = 0){266 267 $this->setOption('errorNum', $error);268 269 if($error){270 return false;271 }272 273 $this->setOption('originName', $name);274 $this->setOption('tmpFileName', $tmpName);275 $arrStr=explode('.', $name); 276 $this->setOption('fileType', strtolower($arrStr[count($arrStr)-1]));277 $this->setOption('fileSize', $size); 278 279 return true;280 }281 /**282 * 283 * 线性删除284 * @access private285 * @param array $array286 * @param int $i287 * @return array;288 */ 289 private function deleteArrayElement($array , $i) { 290 $count = count($array); 291 for ($j = $i; $j < $count; $j ++){ 292 $array[$j] = $array [$j+1]; 293 } 294 array_pop ($array); 295 return $array ; 296 }297 /**298 * 299 * 用于获取上传后文件的文件名300 * @access public301 * @return string302 */303 public function getNewFileName(){304 return $this->newFileName;305 }306 /**307 * 308 * 获取上传错误信息309 * @access private310 * @return string311 */312 private function getError(){313 $str='上传文件'.$this->originName.'时出错:';314 315 switch($this->errorNum){316 case 5: $str .= '初始化参数出错';317 break;318 case 4: $str .= '没有文件被上传'; 319 break;320 case 3: $str .= '文件只被部分上传'; 321 break;322 case 2: $str .= '上传文件超过了HTML表单中MAX_FILE_SIZE选项指定的值';323 break;324 case 1: $str .= '上传文件超过了php.ini 中upload_max_filesize选项的值';325 break;326 case -1: $str .= '末充许的类型';327 break;328 case -2: $str .= '文件过大,上传文件不能超过'.$this->maxSize.'个字节';329 break;330 case -3: $str .= '上传失败';331 break;332 case -4: $str .= '建立存放上传文件目录失败,请重新指定上传目录';333 break;334 case -5: $str .= '必须指定上传文件的路径';335 break;336 default: $str .= '末知错误';337 }338 339 return $str.'';340 }341 /**342 * 343 * 查看错误报告344 * @access public345 * @return string346 */347 public function getErrorMsg() {348 return $this->errorMess;349 }350 }