CodeIgniter 3中do_upload()移除文件名&字符的解决方法咨询
解决CodeIgniter 3上传文件时保留文件名中&字符的问题
问题场景
在CodeIgniter 3中使用do_upload()上传名为「Heavy & Light Vehicles.csv」的文件,请求参数为im_file。设置$config['file_name']为uniqid()拼接原文件名后,上传后的文件名丢失了&字符,实际得到65e5c1262de2d_Heavy_Light_Vehicles.csv,期望保留&得到65e5c1262de2d_Heavy_&_Light_Vehicles.csv。
用户原有代码:
// Upload File Name : ***Heavy & Light Vehicles.csv*** // File post parameter : *im_file* $config['file_name'] = $saved_file_name = uniqid() . '_' . $_FILES['im_file']['name']; $config['allowed_types'] = 'csv'; $config['overwrite'] = TRUE; $this->load->library('upload'); $this->upload->initialize($config); if (!$this->upload->do_upload('im_file')) { $error = array('error' => $this->upload->display_errors()); $im_file = ""; exit(); } else { $filedata = array('upload_data' => $this->upload->data()); print_r($filedata); }
上传后输出的upload_data数组:
[upload_data] => Array ( [file_name] => 65e5c1262de2d_Heavy_Light_Vehicles.csv [file_type] => text/plain [file_path] => D:/wamp/www/project_folder/uploads/import_file/vehicles/ [full_path] => D:/wamp/www/project_folder/uploads/import_file/vehicles/65e5c1262de2d_Heavy_Light_Vehicles.csv [raw_name] => 65e5c1262de2d_Heavy_Light_Vehicles.csv [orig_name] => 65e5c1262de2d_Heavy_Light_Vehicles.csv [client_name] => Heavy & Light Vehicles.csv [file_ext] => .csv [file_size] => 99.2 [is_image] => [image_width] => [image_height] => [image_type] => [image_size_str] => )
原因分析
CodeIgniter 3的Upload类默认会通过_prep_filename()方法清理文件名,该方法调用CI_security::sanitize_filename()函数,默认规则会移除&这类特殊字符,导致文件名中的&被过滤掉。
解决方案
方法一:修改允许的文件名字符(推荐)
在上传配置中添加&到allowed_filename_chars列表,允许该字符出现在文件名中:
// Upload File Name : Heavy & Light Vehicles.csv // File post parameter : im_file $config['file_name'] = uniqid() . '_' . $_FILES['im_file']['name']; $config['allowed_types'] = 'csv'; $config['overwrite'] = TRUE; // 允许&字符出现在文件名中,在默认允许字符基础上添加& $config['allowed_filename_chars'] = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.&'; $this->load->library('upload'); $this->upload->initialize($config); if (!$this->upload->do_upload('im_file')) { $error = array('error' => $this->upload->display_errors()); $im_file = ""; exit(); } else { $filedata = array('upload_data' => $this->upload->data()); print_r($filedata); }
执行后,文件名会保留&字符,得到期望的65e5c1262de2d_Heavy_&_Light_Vehicles.csv。
方法二:手动移动上传文件(绕过框架默认处理)
如果不想修改框架的文件名过滤规则,可以直接使用PHP原生函数move_uploaded_file()手动处理文件上传,完全控制文件名:
// 定义上传目录(确保目录存在且有写入权限) $upload_dir = './uploads/import_file/vehicles/'; // 自定义目标文件名 $saved_file_name = uniqid() . '_' . $_FILES['im_file']['name']; $target_path = $upload_dir . $saved_file_name; // 检查临时文件是否存在 if (isset($_FILES['im_file']['tmp_name']) && is_uploaded_file($_FILES['im_file']['tmp_name'])) { // 移动文件到目标目录 if (move_uploaded_file($_FILES['im_file']['tmp_name'], $target_path)) { // 构造自定义的upload_data数组 $filedata = array( 'upload_data' => array( 'file_name' => $saved_file_name, 'file_type' => $_FILES['im_file']['type'], 'file_path' => $upload_dir, 'full_path' => $target_path, 'raw_name' => pathinfo($saved_file_name, PATHINFO_FILENAME), 'orig_name' => $saved_file_name, 'client_name' => $_FILES['im_file']['name'], 'file_ext' => '.' . pathinfo($saved_file_name, PATHINFO_EXTENSION), 'file_size' => round(filesize($target_path) / 1024, 1) // 转换为KB并保留一位小数 ) ); print_r($filedata); } else { $error = array('error' => '文件移动失败'); $im_file = ""; exit(); } } else { $error = array('error' => '上传文件不存在'); $im_file = ""; exit(); }
这种方法完全绕过了CodeIgniter Upload类的文件名清理逻辑,直接保留原始文件名中的所有字符。
内容的提问来源于stack exchange,提问作者Ganesh Gadge
相关产品推荐
相关产品推荐

