CodeIgniter 文件上传类 分析
来源:互联网 发布:布登勃洛克一家知乎 编辑:程序博客网 时间:2024/05/12 22:48
上传文件普遍的过程:
- 一个上传文件用的表单,允许用户选择一个文件并上传它。
- 当这个表单被提交,该文件被上传到指定的目录。
- 同时,该文件将被验证是否符合您设定的要求。
- 一旦文件上传成功,还要返回一个上传成功的确认窗口。
CodeIgniter的文件上传类首先利用构造函数初始化偏好设置参数:
public function __construct($props = array()){if (count($props) > 0){$this->initialize($props);}log_message('debug', "Upload Class Initialized");}其中调用了成员方法initialize($config = array()):
public function initialize($config = array()){$defaults = array('max_size'=> 0,'max_width'=> 0,'max_height'=> 0,'max_filename'=> 0,'allowed_types'=> "",'file_temp'=> "",'file_name'=> "",'orig_name'=> "",'file_type'=> "",'file_size'=> "",'file_ext'=> "",'upload_path'=> "",'overwrite'=> FALSE,'encrypt_name'=> FALSE,'is_image'=> FALSE,'image_width'=> '','image_height'=> '','image_type'=> '','image_size_str'=> '','error_msg'=> array(),'mimes'=> array(),'remove_spaces'=> TRUE,'xss_clean'=> FALSE,'temp_prefix'=> "temp_file_",'client_name'=> '');foreach ($defaults as $key => $val){if (isset($config[$key])){$method = 'set_'.$key;if (method_exists($this, $method)){$this->$method($config[$key]);}else{$this->$key = $config[$key];}}else{$this->$key = $val;}}// if a file_name was provided in the config, use it instead of the user input// supplied file name for all uploads until initialized again$this->_file_name_override = $this->file_name;}该函数利用:
set_upload_path($path):确保$path末尾只有一个反斜杠
set_filename($path, $filename):如果encrypt_name设置为true,则使用随机加密的字符串作为文件名,否则使用$filename.$i.$file_ext作为文件名
set_image_properties($path = ''):确定图片的宽度、高度、类型
set_allowed_types($types):设置被允许上传的文件类型
set_max_filesize($n)、set_max_filename($n)、set_max_width($n)、set_max_height($n)
set_xss_clean($flag = FALSE):使上传文件通过xss过滤
然后就是执行文件上传过程,do_upload($field = 'userfile'):
do_upload()首先判断$_FILES[$field]是否被设置,如果没有设置,返回false,终止上传:
if ( ! isset($_FILES[$field])){$this->set_error('upload_no_file_selected');return FALSE;}然后判断上传路径,判上传路径是否为一个有效的路径且是否有写的权限:
if ( ! $this->validate_upload_path()){// errors will already be set by validate_upload_path() so just return FALSEreturn FALSE;}validate_upload_path()函数代码如下:
public function validate_upload_path(){if ($this->upload_path == ''){$this->set_error('upload_no_filepath');return FALSE;}if (function_exists('realpath') AND @realpath($this->upload_path) !== FALSE){$this->upload_path = str_replace("\\", "/", realpath($this->upload_path));}if ( ! @is_dir($this->upload_path)){$this->set_error('upload_no_filepath');return FALSE;}if ( ! is_really_writable($this->upload_path)){$this->set_error('upload_not_writable');return FALSE;}$this->upload_path = preg_replace("/(.+?)\/*$/", "\\1/", $this->upload_path);return TRUE;}接着判断文件是否是通过 HTTP POST 上传的,is_uploaded_file()
if ( ! is_uploaded_file($_FILES[$field]['tmp_name'])){$error = ( ! isset($_FILES[$field]['error'])) ? 4 : $_FILES[$field]['error'];switch($error){case 1:// UPLOAD_ERR_INI_SIZE$this->set_error('upload_file_exceeds_limit');break;case 2: // UPLOAD_ERR_FORM_SIZE$this->set_error('upload_file_exceeds_form_limit');break;case 3: // UPLOAD_ERR_PARTIAL$this->set_error('upload_file_partial');break;case 4: // UPLOAD_ERR_NO_FILE$this->set_error('upload_no_file_selected');break;case 6: // UPLOAD_ERR_NO_TMP_DIR$this->set_error('upload_no_temp_directory');break;case 7: // UPLOAD_ERR_CANT_WRITE$this->set_error('upload_unable_to_write_file');break;case 8: // UPLOAD_ERR_EXTENSION$this->set_error('upload_stopped_by_extension');break;default : $this->set_error('upload_no_file_selected');break;}return FALSE;}如果文件是通过HTTP POST上传,则设置上传数据的类变量:
$this->file_temp = $_FILES[$field]['tmp_name'];$this->file_size = $_FILES[$field]['size'];$this->_file_mime_type($_FILES[$field]);$this->file_type = preg_replace("/^(.+?);.*$/", "\\1", $this->file_type);$this->file_type = strtolower(trim(stripslashes($this->file_type), '"'));$this->file_name = $this->_prep_filename($_FILES[$field]['name']);$this->file_ext = $this->get_extension($this->file_name);$this->client_name = $this->file_name;然后判断文件是否是被允许上传的类型:
if ( ! $this->is_allowed_filetype()){$this->set_error('upload_invalid_filetype');return FALSE;}is_allowed_filetype($ignore_mime = FALSE)
public function is_allowed_filetype($ignore_mime = FALSE){if ($this->allowed_types == '*'){return TRUE;}if (count($this->allowed_types) == 0 OR ! is_array($this->allowed_types)){$this->set_error('upload_no_file_types');return FALSE;}$ext = strtolower(ltrim($this->file_ext, '.'));if ( ! in_array($ext, $this->allowed_types)){return FALSE;}// Images get some additional checks$image_types = array('gif', 'jpg', 'jpeg', 'png', 'jpe');if (in_array($ext, $image_types)){if (getimagesize($this->file_temp) === FALSE){return FALSE;}}if ($ignore_mime === TRUE){return TRUE;}$mime = $this->mimes_types($ext);if (is_array($mime)){if (in_array($this->file_type, $mime, TRUE)){return TRUE;}}elseif ($mime == $this->file_type){return TRUE;}return FALSE;}接着确定新名称和类型是否允许:
if ($this->_file_name_override != ''){$this->file_name = $this->_prep_filename($this->_file_name_override);// If no extension was provided in the file_name config item, use the uploaded oneif (strpos($this->_file_name_override, '.') === FALSE){$this->file_name .= $this->file_ext;}// An extension was provided, lets have it!else{$this->file_ext = $this->get_extension($this->_file_name_override);}if ( ! $this->is_allowed_filetype(TRUE)){$this->set_error('upload_invalid_filetype');return FALSE;}}然后将文件大小转换为KB:
if ($this->file_size > 0){$this->file_size = round($this->file_size/1024, 2);}
接着判断文件大小是否被允许:
if ( ! $this->is_allowed_filesize()){$this->set_error('upload_invalid_filesize');return FALSE;}
如果文件是图片还要判断图片的属性是否被允许,宽度、高度
if ( ! $this->is_allowed_dimensions()){$this->set_error('upload_invalid_dimensions');return FALSE;}
接着清楚文件名中的一些特殊字符:<!--、-->、<、>、"、$、=、;、?、/
$this->file_name = $this->clean_file_name($this->file_name);
如果文件名太长,则截断文件名:
if ($this->max_filename > 0){$this->file_name = $this->limit_filename_length($this->file_name, $this->max_filename);}
接着删除空白的文件名
if ($this->remove_spaces == TRUE){$this->file_name = preg_replace("/\s+/", "_", $this->file_name);}
接着验证文件名称:如果存在同名文件,$overwrite设置为TRUE则覆盖文件,如果为FALSE,则在文件名后加数字,如filename1.jpg
$this->orig_name = $this->file_name;if ($this->overwrite == FALSE){$this->file_name = $this->set_filename($this->upload_path, $this->file_name);if ($this->file_name === FALSE){return FALSE;}}
接着使用XSS filter过滤:
if ($this->xss_clean){if ($this->do_xss_clean() === FALSE){$this->set_error('upload_unable_to_write_file');return FALSE;}}
最后把文件移动到上传目录:
if ( ! @copy($this->file_temp, $this->upload_path.$this->file_name)){if ( ! @move_uploaded_file($this->file_temp, $this->upload_path.$this->file_name)){$this->set_error('upload_destination_error');return FALSE;}}
如果上传的是图片则设置文件的一些属性:宽度、高度。
仅作为笔记之用
- CodeIgniter 文件上传类 分析
- 【Codeigniter-Upload类】上传zip/rar文件
- 【Codeigniter-Upload类】阻止上传同名文件
- codeigniter 多文件上传
- CodeIgniter+uploadify上传文件
- codeigniter源码分析-核心文件CodeIgniter.php
- CodeIgniter 加密类分析
- CodeIgniter 装载类 分析
- codeigniter源代码分析之文件加载类 Loader.php
- codeigniter 允许所有类型的文件上传
- CodeIgniter 处理多文件多格式上传
- CodeIgniter 的文件上传控件解析
- codeigniter解决新文件上传问题&&文件上传问题
- CodeIgniter Session类 源代码 分析
- php无刷新文件上传(原创)Codeigniter框架下测试
- codeigniter文件上传时$config["allowed_types"]设置问题
- CodeIgniter 图像处理类 源代码分析
- CodeIgniter 分页类 pagination 源代码分析
- Unity 3D 物理引擎之刚体与碰撞器
- 导出Gerber文件和钻孔数据文件
- 关于LBS项目开发的个人总结
- Android自定义Gallery布局
- Microsoft SQL Server Integration Service文章总结
- CodeIgniter 文件上传类 分析
- Sapera帮助文档
- Linux常见目录介绍
- 按键时js获取键码值
- 一个简单但详细的解释Windows文件映射读取数据文件的例子
- 类
- js正则表达式
- MySql学习
- 键盘键码值