<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()); }?>
总觉得写得不够好 大神们给点建议阿。先谢谢啦
2、既然参数均需在实例化时传入,那么 upload 方法可考虑隐式执行,即在构造函数中直接调用
3、上传文件的控件名本身就存在于 $_FILES 中,为何要显式的传入
4、此类只能处理上传控件不同命的情况,对于同名上传控件就无能为力了。而用 js 动态产生上传控件的需求是比较普遍的
5、目标文件名的生成 $rand_num = date('Ymdhis').rand(0,10000000); 存在一定的风险,单用户测试是没有问题的。但是当多个用户在同一时刻上传时,如何保证 rand(0,10000000) 不重复?
版主 确实global,是多余的。犯了个小错误。谢谢阿。
upload方法隐式执行的话。如果批量上传,上传到某张图片产生错误的时候;需要javascript提示错误。会不会比较麻烦呢。$rand_num = date('Ymdhis').rand(0,10000000);
这个要怎么改呢 只要纯数字组合。加上微秒应该可以吧。
后面添加额外字节不影响jpg的显示,但可以做很多其他事,例如后面添加 eval(...)所以一定要把图片存放的目录执行权限封杀,包括自己存放图片的目录也应该这样
list($msec,$sec) = explode(" ", microtime());
$rand_num = date('Ymdhis').($msec*100000000).rand(0,10000000);
加不加var应该是一样的吧 都是public。我看到很多人家写的类都加,所以就这样写了。