codeigniter 的 encrypt_name 仅生成随机哈希名,非真正加密,不防冲突且不保证 url 安全;生效需每次上传前调用 initialize(),否则配置失效;优先级 file_name > encrypt_name;ci4 中必须用 $file->getname() 获取真实保存名。

CodeIgniter 的 encrypt_name 不是加密,只是生成随机哈希名;它不保证 URL 安全,也不防冲突——除非你同时设 overwrite = FALSE,否则同名上传会直接覆盖旧文件。
为什么 encrypt_name = TRUE 有时没生效?
这个配置只在 $this->upload->do_upload() 执行前生效,且必须在每次调用前确保上传库已用新配置初始化。常见错误是:连续多次上传时复用同一个 upload 实例,但没调用 initialize()。
-
encrypt_name依赖底层的md5(uniqid()),不加盐,不可逆但可预测(对安全性要求高的场景别当真加密用) - 如果同时设置了
file_name,encrypt_name会被忽略——优先级:file_name > encrypt_name - CI3 中若未显式调用
$this->upload->initialize($config),第二次上传仍沿用第一次的配置,导致encrypt_name看似“失效”
手动拼接时间戳 + 原始名的安全写法
想保留原始文件语义又避免重名?别依赖 encrypt_name,自己构造 file_name 更可控。关键点:提取扩展名、过滤非法字符、确保唯一性。
- 用
pathinfo($file['name'], PATHINFO_EXTENSION)拿扩展名,别直接拼$_FILES['userfile']['name']—— 客户端可能伪造后缀 - 时间戳建议用
date('YmdHis') . '_' . mt_rand(100, 999),避免高并发下秒级重复 - 原始名要做清理:
preg_replace('/[^a-zA-Z0-9_\-]/', '_', $orig_name),防止点号被 CI 自动转成下划线(见_prep_filename()函数) - 示例:
$config['file_name'] = date('YmdHis') . '_' . preg_replace('/[^a-zA-Z0-9_\-]/', '_', pathinfo($file['name'], PATHINFO_FILENAME)) . '.' . strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
CI4 中获取最终保存的文件名必须用 getName()
CI4 彻底重构了上传流程,$file->move() 后名字可能已被自动改写(比如加 _1 后缀),此时 $file->getName() 返回的是磁盘上真实存在的文件名,而 $file->getClientName() 始终是原始上传名。
- 不要从
$_FILES或表单字段推导服务器文件名,CI4 的move()可能因overwrite = FALSE自动重命名 - 数据库记录必须用
$file->getName(),否则查不到文件 - 如果你用了
$file->getRandomName(),它返回的是不含路径的随机字符串(如abc123def456.jpg),但实际保存名仍可能被追加序号——所以仍得靠getName()
真正容易被忽略的是:CI3 的 encrypt_name 和 CI4 的 getRandomName() 都不处理文件系统级的竞争条件。如果两个请求几乎同时上传同名文件,且都设 overwrite = FALSE,CI 仍可能生成相同哈希或随机串,导致一个失败。生产环境必须配合原子操作或数据库唯一约束兜底。










