上传文件
处理文件上传对于web应用是非常常见的一个任务。Yii有一些非常有用的内置类。让我们创建一个简单的表单,它允许上传ZIP压缩包,并保存到/uploads
文件夹中。
准备
- 按照官方指南http://www.yiiframework.com/doc-2.0/guide-start-installation.html的描述,使用Composer包管理器创建一个新的应用。
- 创建
@app/web/uploads
文件夹
如何做…
- 我们将会以一个模型开始,创建
@app/models/Upload.php
:
<?php
namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;
class UploadForm extends Model
{
/**
* @var UploadedFile
*/
public $file;
public function rules()
{
return [
['file', 'file', 'skipOnEmpty' => false,
'extensions' => 'zip'],
];
}
public function upload()
{
if ($this->validate()) {
$this->file->saveAs('uploads/' .
$this->file->baseName . '.' . $this->file->extension);
return true;
} else {
return false;
}
}
}
- 现在我们来看控制器,创建
@app/controllers/UploadController.php
:
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use app\models\UploadForm;
use yii\web\UploadedFile;
class UploadController extends Controller
{
public function actionUpload()
{
$model = new UploadForm();
if (Yii::$app->request->isPost) {
$model->file = UploadedFile::getInstance($model,
'file');
if ($model->upload()) {
return $this->renderContent("File {$model->file->name} is uploaded successfully");
}
}
return $this->render('index', ['model' => $model]);
}
}
- 最后是
@app/views/upload/index.php
:
<?php
use yii\widgets\ActiveForm;
use yii\helpers\Html;
?>
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'file')->fileInput() ?>
<?= Html::submitButton('Upload', ['class' => 'btn-success'])?>
<?php ActiveForm::end() ?>
- 现在运行upload控制器,并尝试上传ZIP压缩包和其他文件:
工作原理…
我们使用的模型非常简单,我们只是定义了一个字段,名叫$file
,以及一个使用FileValidator
文件校验器的校验规则,它只读取ZIP文件。
我们创建一个模型的实例,并在提交表单的时候使用$_POST
中的数据填充它:
$model->file = UploadedFile::getInstance($model, 'file');
if ($model->upload()) {
return $this->renderContent("File {$model->file->name} is uploaded successfully");
}
然后我们使用UploadFile::getInstance
,它给我们UploadFile
的实例。当上传文件的时候,它是对$_FILE
数组的封装。通过调用模型的validate
方法,我们确保这个文件是一个ZIP压缩包,然后我们使用UploadFile::saveAs
保存文件。
为了上传文件,HTML表单必须满足如下两个重要的需求:
- 必须使用
POST
方法 enctype
属性必须设置为multipart/form-data
记住你需要添加enctype
选项到表单,这样文件才能正确上传。
我们可以使用Html
帮助类或者带有htmlOptions
集合的ActiveForm
来生成HTML。这里使用的HTML是:
<?= Html::beginForm('', 'post', ['enctype'=>'multipart/form-data'])?>
最后,我们为模型的file属性展示了一个错误和一个字段,并渲染了一个提交按钮。
更多…
为了上传多个文件,Yii2实现了两个特殊的方法。
例如,你已经定义了$imageFiles
,在你的模型、视图文件中所有都是一样的,除了一些细小的差别:
...
<?= $form->field($model, 'imageFiles[]')->fileInput(['multiple' => true, 'accept' => 'image/*']) ?>
...
为了获取所有文件的实例,你必须调用UploadFile::getInstances()
而不是UploadFile::getInstance()
:
..
$model->imageFiles = UploadedFile::getInstances($model, 'imageFiles');
..
可以使用简单的代码来处理并保存多个文件:
foreach ($this->imageFiles as $file) {
$file->saveAs('uploads/' . $file->baseName . '.' .$file->extension);
}
参考
欲了解更多信息,参考: