<html>
<head>
<title>上载文件表单</title></head>
<body>
<form enctype="multipart/form-data" action="index.php" method="post">
请选择文件:<br>
<input name="upload_file" type="file"><br>
<input type="hidden" name="MAX_FILE_SIZE" value="30000">
<input type="submit" value="上传文件">
</form>
</body>
</html>
<?phpdefine(UPLOAD_DIR,'D:\\AppServ\\www\\test\\upload\\');
define(UPLOAD_WEB_DIR,'\\test\\upload\\');class upload_file_class{  var $input_name; //上传file的name
 var $max_size; //最大上传大小 单位kb
 var $allow_ext; //所允许的扩展名
 var $err_info;     //错误信息  /**
     * 构造函数
     *
     * @param  $input_name
     * @param  $max_size
     * @param  $allow_ext   
     * @return 
     */
 function __construct($input_name,$max_size=1024,$allow_ext=array('jpg','png','gif')){   $this->input_name  = $input_name;
  $this->max_size    = $max_size;
  $this->allow_ext   = $allow_ext;
  $this->err_info_arr    = array(   1=>'上传文件大小超过了ini的设定值',
  2=>'上传文件大小超过了表单设定的最大值',
  3=>'文件只有部分被上传',
  4=>'没有文件被上传',
  5=>'上传文件大小超过了允许的设定值',
  6=>'不是允许的上传文件类型',
  7=>'创建目录失败,请确认是否有创建目录的权限',
  8=>'创建文件失败,请重试。',
  9=>'文件上传时产生错误,请重试。'   );  }  /**
     *文件上传 
     *   
     * @return $file_path_arr 上传成功的文件路径数组
     */
 public function upload(){   global $_FILES;
  if( !is_array($this->input_name) )$this->input_name = array($this->input_name);
  $file_path_arr = array();
  foreach ($this->input_name as $k => $input_name ) {
 
  $__F = $_FILES[$input_name];
  if( !empty($__F) ){   if( $__F['error'] > 0 ){   //客户端上传产生错误
  $this->set_err($__F['error']);   }
  else{   $__F['size'] = $__F['size']/1024;
  if( $this->max_size >= $__F['size'] ){
 
  if( $this->check_ext($__F['name']) ){    $save_dir_info = $this->check_dir();
  if( $save_dir_info ){
 
  $rand_num      = date('Ymdhis').rand(0,10000000);
  $ext     = $this->get_img_ext($__F['name']);
  $new_file_name = $rand_num.".{$ext}";
  $full_path     = $save_dir_info['full_dir'].$new_file_name;
  $full_web_path = $save_dir_info['full_web_dir'].$new_file_name;
  if( !file_exists($full_path) ){   if( move_uploaded_file($__F['tmp_name'],$full_path) ){   $file_path_arr[] = array(   'full_path' =>$full_path,
  'full_web_path' =>$full_web_path   );   }
  else{   $this->set_err(9);    //文件上传错误     }   }
  else{   $this->set_err(8);   //文件已存在
 
  }      
 
  }
  else{   $this->set_err(7); //创建目录失败   }   }
  else{   $this->set_err(6); //扩展名非法   }
  }
  else{   $this->set_err(5);     //文件超过设置大小   }         }   }   }
  return $file_path_arr;  }  /**
     * 获取文件扩展名
     *
     * @param  char $file_name  文件名
     * @return ext 扩展名
     */
    public function get_img_ext($file_name) {
        
        if( !empty( $file_name ) ){         $img_info = explode('.',$file_name);
         $ext   = $img_info[count($img_info)-1];
         $ext     = strtolower($ext);
        
        }      
        return $ext;
        
    }
 /**
     * 检查文件合法性
     *
     * @param  char $file_name  文件名
     * @return bool
     */
    public function check_ext($file_name){     $ext = $this->get_img_ext($file_name);
     if(in_array($ext,$this->allow_ext)){     return true;     }
     return false;    }     /**
     * 检查文件目录
     *
     * @return $save_dir_info 保存文件的文件夹信息
     */
    public function check_dir(){     $date    = date("Ymd",time());
     $save_dir_info['full_dir']  = UPLOAD_DIR."{$date}/";
     $save_dir_info['full_web_dir']  = UPLOAD_WEB_DIR."{$date}/";     if(!is_dir( $save_dir_info['full_dir'] )){
    
     if(!mkdir($save_dir_info['full_dir'],0777)){     return false;     }
    
     }
     return $save_dir_info;    }     /**
     * 设置错误信息
     *
     */
 public function set_err($err_code){   $this->err_info = array();
  if(!empty($this->err_info_arr[$err_code])){
 
  $this->err_info['err_code'] = $err_code;
  $this->err_info['err_info'] = $this->err_info_arr[$err_code];   }
  return $this->err_info;  }}?><?php
if( $_FILES ){ echo(date("Y-m-d h:i",time()));
echo('成功上传文件');
echo('<br/>');
$upload_obj = new upload_file_class('upload_file');
print_r($upload_obj->upload()); }?>
总觉得写得不够好  大神们给点建议阿。先谢谢啦

解决方案 »

  1.   

    1、$_FILES 是自动全局变量,无需 global 声明
    2、既然参数均需在实例化时传入,那么 upload 方法可考虑隐式执行,即在构造函数中直接调用
    3、上传文件的控件名本身就存在于 $_FILES 中,为何要显式的传入
    4、此类只能处理上传控件不同命的情况,对于同名上传控件就无能为力了。而用 js 动态产生上传控件的需求是比较普遍的
    5、目标文件名的生成 $rand_num      = date('Ymdhis').rand(0,10000000); 存在一定的风险,单用户测试是没有问题的。但是当多个用户在同一时刻上传时,如何保证 rand(0,10000000) 不重复?
      

  2.   


    版主 确实global,是多余的。犯了个小错误。谢谢阿。
    upload方法隐式执行的话。如果批量上传,上传到某张图片产生错误的时候;需要javascript提示错误。会不会比较麻烦呢。$rand_num      = date('Ymdhis').rand(0,10000000);
    这个要怎么改呢    只要纯数字组合。加上微秒应该可以吧。
      

  3.   

    777 是危险的,任何存放图片的目录都不应该有执行权限更严格的检查是要把jpg“切尾”,但这个就耗资源了,一般设无执行权限就行
      

  4.   

    正常的jpg都以字节FFD9结尾,而且理论上整个文件FFD9只出现一次,就是结尾
    后面添加额外字节不影响jpg的显示,但可以做很多其他事,例如后面添加 eval(...)所以一定要把图片存放的目录执行权限封杀,包括自己存放图片的目录也应该这样
      

  5.   

    snmr_com   还有这样的事情,那按你的说法;那句创建目录代码要怎样改。
      

  6.   

    根据需要参看chmod()的mode说明
      

  7.   

    版主 这样行不  
    list($msec,$sec) = explode(" ", microtime());
    $rand_num        =  date('Ymdhis').($msec*100000000).rand(0,10000000);
      

  8.   


    加不加var应该是一样的吧   都是public。我看到很多人家写的类都加,所以就这样写了。