Home  • Framework • Yii

Uploading Files using Yii

1. Creating Models 2. Rendering File Input 3. Wiring Up 4. Uploading Multiple Files Uploading files in Yii is usually done with the help of yiiwebUploadedFile which encapsulates each uploaded file as an UploadedFile object. Combined with yiiwidgetsActiveForm and models, you can easily implement a secure file uploading mechanism.

Creating Models

Like working with plain text inputs, to upload a single file you would create a model class and use an attribute of the model to keep the uploaded file instance. You should also declare a validation rule to validate the file upload. For example,
namespace appmodels;

use yiiaseModel;
use yiiwebUploadedFile;

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;
        }
    }
}
In the code above, the imageFile attribute is used to keep the uploaded file instance. It is associated with a file validation rule which uses yiivalidatorsFileValidator to ensure a file with extension name png or jpg is uploaded. The upload() method will perform the validation and save the uploaded file on the server. The file validator allows you to check file extensions, size, MIME type, etc. Please refer to the Core Validators section for more details.
Tip: If you are uploading an image, you may consider using the image validator instead. The image validator is implemented via yiivalidatorsImageValidator which verifies if an attribute has received a valid image that can be then either saved or processed using the Imagine Extension.

Rendering File Input

Next, create a file input in a view:
<?php
use yiiwidgetsActiveForm;
?>

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

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

    <button>Submit</button>

<?php ActiveForm::end() ?>
It is important to remember that you add the enctype option to the form so that the file can be properly uploaded. The fileInput() call will render a <input type="file"> tag which will allow users to select a file to upload.

Wiring Up

Now in a controller action, write the code to wire up the model and the view to implement file uploading:
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->imageFile = UploadedFile::getInstance($model, 'imageFile');
            if ($model->upload()) {
                // file is uploaded successfully
                return;
            }
        }

        return $this->render('upload', ['model' => $model]);
    }
}
In the above code, when the form is submitted, the yiiwebUploadedFile::getInstance() method is called to represent the uploaded file as an UploadedFile instance. We then rely on the model validation to make sure the uploaded file is valid and save the file on the server.

Uploading Multiple Files

You can also upload multiple files at once, with some adjustments to the code listed in the previous subsections. First you should adjust the model class by adding the maxFiles option in the file validation rule to limit the maximum number of files allowed to upload. Setting maxFiles to 0 means there is no limit on the number of files that can be uploaded simultaneously. The maximum number of files allowed to be uploaded simultaneously is also limited with PHP directive max_file_uploads, which defaults to 20. The upload() method should also be updated to save the uploaded files one by one.
namespace appmodels;

use yiiaseModel;
use yiiwebUploadedFile;

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;
        }
    }
}
In the view file, you should add the multiple option to the fileInput() call so that the file upload field can receive multiple files:
<?php
use yiiwidgetsActiveForm;
?>

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

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

    <button>Submit</button>

<?php ActiveForm::end() ?>
And finally in the controller action, you should call UploadedFile::getInstances() instead of UploadedFile::getInstance() to assign an array of UploadedFile instances to UploadForm::imageFiles.
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->imageFiles = UploadedFile::getInstances($model, 'imageFiles');
            if ($model->upload()) {
                // file is uploaded successfully
                return;
            }
        }

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

Comments 1


http://www.yiiframework.com/doc-2.0/guide-intro-yii.html

Share

Copyright © 2024. Powered by Intellect Software Ltd