上传文件

处理文件上传对于web应用是非常常见的一个任务。Yii有一些非常有用的内置类。让我们创建一个简单的表单,它允许上传ZIP压缩包,并保存到/uploads文件夹中。

准备

  1. 按照官方指南http://www.yiiframework.com/doc-2.0/guide-start-installation.html的描述,使用Composer包管理器创建一个新的应用。
  2. 创建@app/web/uploads文件夹

如何做…

  1. 我们将会以一个模型开始,创建@app/models/Upload.php
  1. <?php
  2. namespace app\models;
  3. use yii\base\Model;
  4. use yii\web\UploadedFile;
  5. class UploadForm extends Model
  6. {
  7. /**
  8. * @var UploadedFile
  9. */
  10. public $file;
  11. public function rules()
  12. {
  13. return [
  14. ['file', 'file', 'skipOnEmpty' => false,
  15. 'extensions' => 'zip'],
  16. ];
  17. }
  18. public function upload()
  19. {
  20. if ($this->validate()) {
  21. $this->file->saveAs('uploads/' .
  22. $this->file->baseName . '.' . $this->file->extension);
  23. return true;
  24. } else {
  25. return false;
  26. }
  27. }
  28. }
  1. 现在我们来看控制器,创建@app/controllers/UploadController.php
  1. <?php
  2. namespace app\controllers;
  3. use Yii;
  4. use yii\web\Controller;
  5. use app\models\UploadForm;
  6. use yii\web\UploadedFile;
  7. class UploadController extends Controller
  8. {
  9. public function actionUpload()
  10. {
  11. $model = new UploadForm();
  12. if (Yii::$app->request->isPost) {
  13. $model->file = UploadedFile::getInstance($model,
  14. 'file');
  15. if ($model->upload()) {
  16. return $this->renderContent("File {$model->file->name} is uploaded successfully");
  17. }
  18. }
  19. return $this->render('index', ['model' => $model]);
  20. }
  21. }
  1. 最后是@app/views/upload/index.php
  1. <?php
  2. use yii\widgets\ActiveForm;
  3. use yii\helpers\Html;
  4. ?>
  5. <?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
  6. <?= $form->field($model, 'file')->fileInput() ?>
  7. <?= Html::submitButton('Upload', ['class' => 'btn-success'])?>
  8. <?php ActiveForm::end() ?>
  1. 现在运行upload控制器,并尝试上传ZIP压缩包和其他文件:

上传文件 - 图1

工作原理…

我们使用的模型非常简单,我们只是定义了一个字段,名叫$file,以及一个使用FileValidator文件校验器的校验规则,它只读取ZIP文件。

我们创建一个模型的实例,并在提交表单的时候使用$_POST中的数据填充它:

  1. $model->file = UploadedFile::getInstance($model, 'file');
  2. if ($model->upload()) {
  3. return $this->renderContent("File {$model->file->name} is uploaded successfully");
  4. }

然后我们使用UploadFile::getInstance,它给我们UploadFile的实例。当上传文件的时候,它是对$_FILE数组的封装。通过调用模型的validate方法,我们确保这个文件是一个ZIP压缩包,然后我们使用UploadFile::saveAs保存文件。

为了上传文件,HTML表单必须满足如下两个重要的需求:

  • 必须使用POST方法
  • enctype属性必须设置为multipart/form-data

记住你需要添加enctype选项到表单,这样文件才能正确上传。

我们可以使用Html帮助类或者带有htmlOptions集合的ActiveForm来生成HTML。这里使用的HTML是:

  1. <?= Html::beginForm('', 'post', ['enctype'=>'multipart/form-data'])?>

最后,我们为模型的file属性展示了一个错误和一个字段,并渲染了一个提交按钮。

更多…

为了上传多个文件,Yii2实现了两个特殊的方法。

例如,你已经定义了$imageFiles,在你的模型、视图文件中所有都是一样的,除了一些细小的差别:

  1. ...
  2. <?= $form->field($model, 'imageFiles[]')->fileInput(['multiple' => true, 'accept' => 'image/*']) ?>
  3. ...

为了获取所有文件的实例,你必须调用UploadFile::getInstances()而不是UploadFile::getInstance()

  1. ..
  2. $model->imageFiles = UploadedFile::getInstances($model, 'imageFiles');
  3. ..

可以使用简单的代码来处理并保存多个文件:

  1. foreach ($this->imageFiles as $file) {
  2. $file->saveAs('uploads/' . $file->baseName . '.' .$file->extension);
  3. }

参考

欲了解更多信息,参考: