# 文件上传
在Yii里上传文件通常使用yii\web\UploadedFile类, 它把每个上传的文件封装成 `UploadedFile` 对象。 结合yii\widgets\ActiveForm和[models](http://www.yiichina.com/doc/guide/2.0/structure-models),你可以轻松实现安全的上传文件机制。
## 创建模型
和普通的文本输入框类似,当要上传一个文件时,你需要创建一个模型类并且用其中的某个属性来接收上传的文件实例。 你还需要声明一条验证规则以验证上传的文件。 举例来讲,
~~~
namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;
class UploadForm extends Model
{
/**
* @var UploadedFile
*/
public $imageFile;
public function rules()
{
return [
[['imageFile'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
];
}
public function upload()
{
if ($this->validate()) {
$this->imageFile->saveAs('uploads/' . $this->imageFile->baseName . '.' . $this->imageFile->extension);
return true;
} else {
return false;
}
}
}
~~~
在以上代码里,`imageFile` 属性用于接收上传的文件实例。它对应一条`file` 验证规则, 该规则使用 yii\validators\FileValidator 来确保只上传扩展名为 `png` 或 `jpg` 的文件。 `upload()` 方法会执行该验证并且把上传的文件保存在服务器上。
通过 `file` 验证器,你可以检查文件的扩展名,大小,MIME类型等等。详情请查阅 [Core Validatators](http://www.yiichina.com/doc/guide/2.0/tutorial-core-validators#file) 章节。
>提示: 如果你要上传的是一张图片,可以考虑使用`image`验证器。 `image` 验证器是通过yii\validators\ImageValidator实现验证的,确保对应的模型属性 收到的文件是有效的图片文件,然后才保存,或者使用扩展类[Imagine Extension](https://github.com/yiisoft/yii2-imagine)进行处理.
## 渲染文件输入
接下来,在视图里创建一个文件输入控件
~~~
<?php
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'imageFile')->fileInput() ?>
<button>Submit</button>
<?php ActiveForm::end() ?>
~~~
需要注意的是要记得在表单选项里加入 `enctype` 属性以确保文件能被正常上传。 `fileInput()` 方法会渲染一个 `<input type="file">` 标签,让用户可以选择一个文件上传。
## 视图和模型的连接
现在,在控制器方法里编写连接模型和视图的代码以实现文件上传。
~~~
namespace app\controllers;
use Yii;
use yii\web\Controller;
use app\models\UploadForm;
use yii\web\UploadedFile;
class SiteController extends Controller
{
public function actionUpload()
{
$model = new UploadForm();
if (Yii::$app->request->isPost) {
$model->imageFile = UploadedFile::getInstance($model, 'imageFile');
if ($model->upload()) {
// 文件上传成功
return;
}
}
return $this->render('upload', ['model' => $model]);
}
}
~~~
在上面的代码里,当提交表单的时候,yii\web\UploadedFile::getInstance()方法就被调用, 上传的文件用一个 `UploadedFile` 实例表示。然后,我们依靠模型的验证规则确保上传的文件是有效的, 并将文件保存在服务器上。
## 上传多个文件
将前面所述的代码做一些调整,也可以一次性上传多个文件。
首先你得调整模型类,在 `file` 验证规则里增加一个 `maxFiles` 选项,用以限制一次上传文件的最大数量。 `upload()`方法也得修改, 以便一个一个地保存上传的文件。
~~~
namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;
class UploadForm extends Model
{
/**
* @var UploadedFile[]
*/
public $imageFiles;
public function rules()
{
return [
[['imageFiles'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg', 'maxFiles' => 4],
];
}
public function upload()
{
if ($this->validate()) {
foreach ($this->imageFiles as $file) {
$file->saveAs('uploads/' . $file->baseName . '.' . $file->extension);
}
return true;
} else {
return false;
}
}
}
~~~
在视图文件里,你需要把 `multiple` 选项添加到`fileInput()`函数调用里, 这样文件输入控件就可以接收多个文件。
~~~
<?php
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'imageFiles[]')->fileInput(['multiple' => true, 'accept' => 'image/*']) ?>
<button>Submit</button>
<?php ActiveForm::end() ?>
~~~
最后,在控制器的 action 方法中,你应该调用 `UploadedFile::getInstances()` 而不是 `UploadedFile::getInstance()` 来把`UploadedFile` 实例数组赋值给 `UploadForm::imageFiles`。
~~~
namespace app\controllers;
use Yii;
use yii\web\Controller;
use app\models\UploadForm;
use yii\web\UploadedFile;
class SiteController extends Controller
{
public function actionUpload()
{
$model = new UploadForm();
if (Yii::$app->request->isPost) {
$model->imageFiles = UploadedFile::getInstances($model, 'imageFiles');
if ($model->upload()) {
// 文件上传成功
return;
}
}
return $this->render('upload', ['model' => $model]);
}
}
~~~
- 介绍(Introduction)
- 关于 Yii(About Yii)
- 从 Yii 1.1 升级(Upgrading from Version 1.1)
- 入门(Getting Started)
- 安装 Yii(Installing Yii)
- 运行应用(Running Applications)
- 第一次问候(Saying Hello)
- 使用 Forms(Working with Forms)
- 玩转 Databases(Working with Databases)
- 用 Gii 生成代码(Generating Code with Gii)
- 更上一层楼(Looking Ahead)
- 应用结构(Application Structure)
- 结构概述(Overview)
- 入口脚本(Entry Scripts)
- 应用(Applications)
- 应用组件(Application Components)
- 控制器(Controllers)
- 模型(Models)
- 视图(Views)
- 模块(Modules)
- 过滤器(Filters)
- 小部件(Widgets)
- 前端资源(Assets)
- 扩展(Extensions)
- 请求处理(Handling Requests)
- 运行概述(Overview)
- 引导(Bootstrapping)
- 路由引导与创建 URL(Routing and URL Creation)
- 请求(Requests)
- 响应(Responses)
- Sessions and Cookies
- 错误处理(Handling Errors)
- 日志(Logging)
- 关键概念(Key Concepts)
- 组件(Components)
- 属性(Properties)
- 事件(Events)
- 行为(Behaviors)
- 配置(Configurations)
- 别名(Aliases)
- 类自动加载(Class Autoloading)
- 服务定位器(Service Locator)
- 依赖注入容器(Dependency Injection Container)
- 配合数据库工作(Working with Databases)
- 数据库访问(Data Access Objects): 数据库连接、基本查询、事务和模式操作
- 查询生成器(Query Builder): 使用简单抽象层查询数据库
- 活动记录(Active Record): 活动记录对象关系映射(ORM),检索和操作记录、定义关联关系
- 数据库迁移(Migrations): 在团体开发中对你的数据库使用版本控制
- Sphinx
- Redis
- MongoDB
- ElasticSearch
- 接收用户数据(Getting Data from Users)
- 创建表单(Creating Forms)
- 输入验证(Validating Input)
- 文件上传(Uploading Files)
- 收集列表输入(Collecting Tabular Input)
- 多模型同时输入(Getting Data for Multiple Models)
- 显示数据(Displaying Data)
- 格式化输出数据(Data Formatting)
- 分页(Pagination)
- 排序(Sorting)
- 数据提供器(Data Providers)
- 数据小部件(Data Widgets)
- 操作客户端脚本(Working with Client Scripts)
- 主题(Theming)
- 安全(Security)
- 认证(Authentication)
- 授权(Authorization)
- 处理密码(Working with Passwords)
- 客户端认证(Auth Clients)
- 安全领域的最佳实践(Best Practices)
- 缓存(Caching)
- 概述(Overview)
- 数据缓存(Data Caching)
- 片段缓存(Fragment Caching)
- 分页缓存(Page Caching)
- HTTP 缓存(HTTP Caching)
- RESTful Web 服务
- 快速入门(Quick Start)
- 资源(Resources)
- 控制器(Controllers)
- 路由(Routing)
- 格式化响应(Response Formatting)
- 授权验证(Authentication)
- 速率限制(Rate Limiting)
- 版本化(Versioning)
- 错误处理(Error Handling)
- 开发工具(Development Tools)
- 调试工具栏和调试器(Debug Toolbar and Debugger)
- 使用 Gii 生成代码(Generating Code using Gii)
- TBD 生成 API 文档(Generating API Documentation)
- 测试(Testing)
- 概述(Overview)
- 搭建测试环境(Testing environment setup)
- 单元测试(Unit Tests)
- 功能测试(Functional Tests)
- 验收测试(Acceptance Tests)
- 测试夹具(Fixtures)
- 高级专题(Special Topics)
- 高级应用模版(Advanced Project Template)
- 从头构建自定义模版(Building Application from Scratch)
- 控制台命令(Console Commands)
- 核心验证器(Core Validators)
- 国际化(Internationalization)
- 收发邮件(Mailing)
- 性能优化(Performance Tuning)
- 共享主机环境(Shared Hosting Environment)
- 模板引擎(Template Engines)
- 集成第三方代码(Working with Third-Party Code)
- 小部件(Widgets)
- Bootstrap 小部件(Bootstrap Widgets)
- jQuery UI 小部件(jQuery UI Widgets)
- 助手类(Helpers)
- 助手一览(Overview)
- Array 助手(ArrayHelper)
- Html 助手(Html)
- Url 助手(Url)