介绍 入门 应用结构 请求处理 关键概念 配合数据库工作 接收用户数据 显示数据 安全 缓存 RESTfulWeb服务 开发工具 测试 高级专题 小部件 助手类 其他

发布于 2015-08-01 11:30:49 | 361 次阅读 | 评论: 0 | 来源: 网络整理

Uploading files in Yii is done via a form model, its validation rules and some controller code. Let's review what's required to handle uploads properly.

Uploading single file

First of all, you need to create a model that will handle file uploads. Create models/UploadForm.php with the following content:

namespace appmodels;

use yiibaseModel;
use yiiwebUploadedFile;

/**
 * UploadForm is the model behind the upload form.
 */
class UploadForm extends Model
{
    /**
     * @var UploadedFile file attribute
     */
    public $file;

    /**
     * @return array the validation rules.
     */
    public function rules()
    {
        return [
            [['file'], 'file'],
        ];
    }
}

In the code above, we've created a model UploadForm with an attribute file that will become <input type="file"> in the HTML form. The attribute has the validation rule named file that uses yiivalidatorsFileValidator.

Form view

Next, create a view that will render the form:

<?php
use yiiwidgetsActiveForm;
?>

<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>

<?= $form->field($model, 'file')->fileInput() ?>

<button>Submit</button>

<?php ActiveForm::end() ?>

The 'enctype' => 'multipart/form-data' is necessary because it allows file uploads. fileInput() represents a form input field.

Controller

Now create the controller that connects the form and the model together:

namespace appcontrollers;

use Yii;
use yiiwebController;
use appmodelsUploadForm;
use yiiwebUploadedFile;

class SiteController extends Controller
{
    public function actionUpload()
    {
        $model = new UploadForm();

        if (Yii::$app->request->isPost) {
            $model->file = UploadedFile::getInstance($model, 'file');

            if ($model->file && $model->validate()) {                
                $model->file->saveAs('uploads/' . $model->file->baseName . '.' . $model->file->extension);
            }
        }

        return $this->render('upload', ['model' => $model]);
    }
}

Instead of model->load(...), we are using UploadedFile::getInstance(...). yiiwebUploadedFile does not run the model validation, rather it only provides information about the uploaded file. Therefore, you need to run the validation manually via $model->validate() to trigger the yiivalidatorsFileValidator. The validator expects that the attribute is an uploaded file, as you see in the core framework code:

if (!$file instanceof UploadedFile || $file->error == UPLOAD_ERR_NO_FILE) {
    return [$this->uploadRequired, []];
}

If the validation is successful, then we're saving the file:

$model->file->saveAs('uploads/' . $model->file->baseName . '.' . $model->file->extension);

If you're using the "basic" project template, then folder uploads should be created under web.

That's it. Load the page and try uploading. Uploads should end up in basic/web/uploads.

Validation

It's often required to adjust validation rules to accept certain files only or require uploading. Below we'll review some common rule configurations.

Required

If you need to make the file upload mandatory, use skipOnEmpty like the following:

public function rules()
{
    return [
        [['file'], 'file', 'skipOnEmpty' => false],
    ];
}

MIME type

It is wise to validate the type of file uploaded. FileValidator has the property $extensions for this purpose:

public function rules()
{
    return [
        [['file'], 'file', 'extensions' => 'gif, jpg'],
    ];
}

By default it will validate against file content mime type corresponding to extension specified. For gif it will be image/gif, for jpg it will be image/jpeg.

Note that some mime types can't be detected properly by PHP's fileinfo extension that is used by file validator. For example, csv files are detected as text/plain instead of text/csv. You can turn off such behavior by setting checkExtensionByMimeType to false and specifying mime types manually:

public function rules()
{
    return [
        [['file'], 'file', 'checkExtensionByMimeType' => false, 'extensions' => 'csv', 'mimeTypes' => 'text/plain'],
    ];
}

List of common media types

Image properties

If you upload an image, yiivalidatorsImageValidator may come in handy. It verifies if an attribute received a valid image that can be then either saved or processed using the Imagine Extension.

Uploading multiple files

If you need to upload multiple files at once, some adjustments are required.

Model:

class UploadForm extends Model
{
    /**
     * @var UploadedFile|Null file attribute
     */
    public $file;

    /**
     * @return array the validation rules.
     */
    public function rules()
    {
        return [
            [['file'], 'file', 'maxFiles' => 10], // <--- here!
        ];
    }
}

View:

<?php
use yiiwidgetsActiveForm;

$form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]);
?>

<?= $form->field($model, 'file[]')->fileInput(['multiple' => true]) ?>

    <button>Submit</button>

<?php ActiveForm::end(); ?>

The difference is the following line:

<?= $form->field($model, 'file[]')->fileInput(['multiple' => true]) ?>

Controller:

namespace appcontrollers;

use Yii;
use yiiwebController;
use appmodelsUploadForm;
use yiiwebUploadedFile;

class SiteController extends Controller
{
    public function actionUpload()
    {
        $model = new UploadForm();

        if (Yii::$app->request->isPost) {
            $model->file = UploadedFile::getInstances($model, 'file');
            
            if ($model->file && $model->validate()) {
                foreach ($model->file as $file) {
                    $file->saveAs('uploads/' . $file->baseName . '.' . $file->extension);
                }
            }
        }

        return $this->render('upload', ['model' => $model]);
    }
}

There are two differences from single file upload. First is that UploadedFile::getInstances($model, 'file'); is used instead of UploadedFile::getInstance($model, 'file');. The former returns instances for all uploaded files while the latter gives you only a single instance. The second difference is that we're doing foreach and saving each file.

最新网友评论  共有(0)条评论 发布评论 返回顶部

Copyright © 2007-2017 PHPERZ.COM All Rights Reserved   冀ICP备14009818号  版权声明  广告服务