在yii2中需自定义文件名生成器解决中文乱码等问题:创建继承yii\base\component的filenamegenerator类,实现generate()方法生成带前缀、安全名、时间戳和随机数的文件名,并在main.php中注册为filenamegenerator组件,上传时通过yii::$app->filenamegenerator调用。

在Yii2项目中批量上传图片时,系统默认用原始文件名保存,导致中文名乱码、重名覆盖、URL不友好等问题,必须替换为可控的自定义文件名生成逻辑。
创建文件名生成器类
在 common/components 目录下新建 FileNameGenerator.php 文件。
类必须继承 yii\base\Component,否则无法被Yii容器识别和调用。
写入以下代码:
namespace common\components;
use yii\base\Component;
use yii\helpers\StringHelper;
class FileNameGenerator extends Component
{
public function generate($uploadedFile, $prefix = 'img')
{
$ext = $uploadedFile->extension;
$baseName = StringHelper::basename($uploadedFile->baseName);
$safeName = preg_replace('/[^\w\-_\.]/', '_', $baseName);
$timestamp = date('YmdHis');
$rand = str_pad(dechex(rand(1000, 9999)), 4, '0', STR_PAD_LEFT);
return sprintf('%s_%s_%s_%s.%s', $prefix, $safeName, $timestamp, $rand, $ext);
}
}
注册组件到应用配置
打开 common/config/main.php(或 main-local.php),在 components 数组中添加:
'fileNameGenerator' => [
'class' => 'common\components\FileNameGenerator'
],
这一步必须完成,否则后续调用 Yii::$app->fileNameGenerator 会抛出 Unknown Component ID 异常。
在上传模型中调用生成器
假设你已有一个上传模型 UploadForm.php,位于 common/models/UploadForm.php。
在 upload() 方法中,替换原生的 $file->baseName . '.' . $file->extension 逻辑:
第一步:在方法顶部获取组件实例:
【$generator = Yii::$app->fileNameGenerator;】
第二步:调用生成器生成新文件名:
$newFileName = $generator->generate($this->imageFile, 'article');
第三步:使用新文件名保存:
$this->imageFile->saveAs('uploads/' . $newFileName);
注意:不要直接拼接路径,saveAs() 的参数必须是完整相对路径(从入口脚本所在目录起算);若写成 './uploads/' 或 __DIR__ . '/uploads/' 会导致保存失败。
扩展用法:按日期子目录自动分发
方法一:修改 generate() 方法,返回带路径前缀的完整字符串
在 generate() 方法末尾改写为:
【$datePath = date('Y/m/d');】
return $datePath . '/' . sprintf('%s_%s_%s_%s.%s', $prefix, $safeName, $timestamp, $rand, $ext);
方法二:在控制器中组合路径(更灵活)
先确保 uploads 目录存在:
if (!is_dir('uploads')) { mkdir('uploads', 0755, true); }
再动态创建日期子目录:
$dateDir = 'uploads/' . date('Y/m/d');
if (!is_dir($dateDir)) { mkdir($dateDir, 0755, true); }
然后调用:
$this->imageFile->saveAs($dateDir . '/' . $newFileName);











