View on GitHub

yii2-cookbook-chinese

Yii Application Development Cookbook(Third Edition)中文翻译

上传文件

处理文件上传对于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
<?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;
        }
    }
}
  1. 现在我们来看控制器,创建@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]);
    }
}
  1. 最后是@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() ?>
  1. 现在运行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表单必须满足如下两个重要的需求:

记住你需要添加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);
}

参考

欲了解更多信息,参考: