Yii2安全文件上传需四步:1.模型中声明$-file为UploadedFile类型;2.rules()设'skipOnEmpty'=>false;3.'extensions'=>'jpg, png, gif'(逗号后空格);4.加'mimeTypes'双重校验;视图中ActiveForm必须设'enctype'=>'multipart/form-data';控制器用getInstance()获取文件,validate()通过后再saveAs()。

在Yii2项目中快速实现安全可靠的文件上传功能,避免反复调试路径、权限和验证规则导致开发停滞。
创建带文件验证的模型类
新建 app\models\UploadForm.php,定义文件属性并绑定验证规则。
第一步:声明 $file 属性为 yii\web\UploadedFile 类型,这是接收上传实例的唯一合法方式;不这样做会导致 getInstance() 返回 null。
第二步:在 rules() 中添加 file 验证器,必须显式指定 'skipOnEmpty' => false,否则空文件提交时验证会跳过,留下安全隐患。
第三步:扩展名限制写成 'extensions' => 'jpg, png, gif',注意逗号后要留空格,否则 Yii2 会把 'jpg,png' 当作一个扩展名处理,导致 png 文件被拒。
第四步:加上 'mimeTypes' => 'image/jpeg, image/png, image/gif' 双重校验,仅靠扩展名可被轻易伪造,MIME 类型由服务端解析真实内容头决定,更可靠。
视图中渲染上传表单
使用 ActiveForm 必须开启 multipart 编码,否则浏览器根本不会发送文件数据。
在视图中调用 ActiveForm::begin() 时,【options 必须包含 'enctype' => 'multipart/form-data'】,漏掉这行,整个表单就退化为普通文本提交,文件字段形同虚设。
直接写 $form->field($model, 'file')->fileInput() 即可生成标准文件控件,无需额外 JS 或 HTML 标签。
如果需要多文件上传,把属性名改成 'file[]' 并在 fileInput() 的 options 里加 'multiple' => true,后端接收逻辑需同步改为 UploadedFile::getInstances()。
控制器中完成保存逻辑
方法一:基础保存(适用于简单场景)
在控制器 action 中调用 $file = UploadedFile::getInstance($model, 'file') 获取实例;若为空则跳过后续操作,避免调用 saveAs() 报错。
手动构建保存路径,例如 $path = 'uploads/' . date('Ymd') . '/';,再用 mkdir($path, 0777, true) 创建嵌套目录;第三个参数 true 不可省略,否则遇到 uploads/20260806/ 这类两级路径会失败。
最后执行 $file->saveAs($path . $file->baseName . '.' . $file->extension) 完成落盘。
方法二:模型内封装保存(推荐用于复用)
在模型中定义 upload() 方法,内部先调用 $this->validate(),验证失败直接返回 false;这一步必须放在 saveAs() 前,否则可能绕过类型检查保存恶意文件。
保存路径建议用 Yii::getAlias('@webroot') . '/uploads/' 拼接,比硬编码更适应不同部署环境。
保存成功后,可将相对路径(如 'uploads/20260806/photo.jpg')赋值给模型其他属性,便于存入数据库。
配置上传根目录别名
在 common/config/bootstrap.php 中添加一行:Yii::setAlias('uploads', dirname(dirname(__DIR__)) . '/frontend/web/uploads');
这行代码让所有模块都能统一引用 @uploads 别名,避免各处硬写路径出错;【未配置此别名,后续使用 @uploads 将触发 Yii 异常并中断请求】。
确保对应物理目录存在且 Web 服务器进程有写权限,Linux 下常用 chmod -R 775 uploads,Windows 下检查 IIS 或 Apache 用户权限。


















