How to upload a file using a model

37 followers

First declare an attribute to store the file name in the model class (either a form model or an active record model). Also declare a file validation rule for this attribute to ensure a file is uploaded with specific extension name.

class Item extends CActiveRecord
{
    public $image;
    // ... other attributes
 
    public function rules()
    {
        return array(
            array('image', 'file', 'types'=>'jpg, gif, png'),
        );
    }
}

Then, in the controller class define an action method to render the form and collect user-submitted data.

class ItemController extends CController
{
    public function actionCreate()
    {
        $model=new Item;
        if(isset($_POST['Item']))
        {
            $model->attributes=$_POST['Item'];
            $model->image=CUploadedFile::getInstance($model,'image');
            if($model->save())
            {
                $model->image->saveAs('path/to/localFile');
                // redirect to success page
            }
        }
        $this->render('create', array('model'=>$model));
    }
}

Finally, create the action view and generate a file upload field.

<?php echo CHtml::form('','post',array('enctype'=>'multipart/form-data')); ?>
...
<?php echo CHtml::activeFileField($model, 'image'); ?>
...
<?php echo CHtml::endForm(); ?>

Links ΒΆ

Total 9 comments

#6012 report it
rrbot at 2011/12/05 06:34pm
"File cannot be blank"

If you are having problems with Updating a model with a file, where you want the file to be empty but get "File cannot be blank", adjust your rule accordingly:

array('file', 'file', 'types'=>'jpg', 'allowEmpty' => true),

If you only want this to be empty on update, you could use a scenerio.

#5496 report it
devric at 2011/10/16 09:32pm
How to save in views for noob

Hi i've followed the guide and add the submit button to the view, but it does not submit, how do i submit this?

<? echo CHtml::form('', 'post', array('enctype'=>'multipart/form-data')); ?>
<? echo CHtml::activeFileField($model, 'image'); ?>
<?php echo CHtml::submitButton('Submit'); ?>
<? echo CHtml::endForm(); ?>
#5354 report it
khobaucuatui at 2011/10/06 11:00am
validation ajax

I can't validation ajax with field image. It error "Image cannot be blank".

#3970 report it
Kabinenkoffer at 2011/05/24 07:07am
Controller / Model

A Question/Suggestion:

If you put this line: $model->image=CUploadedFile::getInstance($model,'image');

in your model under beforeSave() and the file handling in afterSave() you can leave the controller untouched. for me this is usefull beause if you add more file uploads or change something you can just change everything in the model.

#3217 report it
ghadad at 2011/03/25 05:38pm
and dont forgot adding multipart/form-data option to update form !
<?php $form=$this->beginWidget('CActiveForm', array(
    'id'=>'company-form',
    'enableAjaxValidation'=>true,
        'htmlOptions'=>array('enctype'=>'multipart/form-data'),
));
#3137 report it
thim at 2011/03/20 10:20am
File upload and update / error actions

The example above is great, but if you are working with a CRUD interface, then there is a need for a "UPDATE" action. If you update fields but dont upload any files the previous files will be "reset" (made empty) in the model. To prevent this you need to extend the code above.

This approach is based on the explanation from tri, see forum topic >>
http://www.yiiframework.com/forum/index.php?/topic/5419-optional-upload-file-when-update-a-record/page__view__findpost__p__27940

My example:

MODEL:

public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
...
            array('image', 'unsafe'),
...
}

By making the image unsafe the input values for the image field wont be set by $model->attributes=$_POST['Events'];

This allows us to use CUploadedFile data object to set the image data.

CONTROLLER:

/**
     * Updates a particular model.
     * If update is successful, the browser will be redirected to the 'view' page.
     * @param integer $id the ID of the model to be updated
     */
    public function actionUpdate($id)
    {
        $model=$this->loadModel($id);
 
        // Uncomment the following line if AJAX validation is needed
        // $this->performAjaxValidation($model);
 
        if(isset($_POST['Events']))
        {
            $model->attributes=$_POST['Events'];
 
            $file_image = CUploadedFile::getInstance($model,'image');
 
            if ( (is_object($file_flyer) && get_class($file_flyer)==='CUploadedFile'))
                $model->flyer = $file_flyer;
 
            if($model->save())
            {
                if (is_object($file_flyer))
                    $model->flyer->saveAs(Yii::app()->basePath.'/../files/flyers/'.$model->flyer);
 
 
                //$this->redirect(array('update','id'=>$model->id));
 
            }
        }
 
        $this->render('update',array(
            'model'=>$model,
        ));
    }

The first "if" check if the upload object is being loaded and filled with the uploaded file. If this is the case then the model->image gets an update otherwise the previous uploaded file remains.

The second "if" in the save will actually save the file on the webserver.

Hope this helps for those who are struggling with the file upload

#2242 report it
beninblack at 2010/11/30 07:09pm
FYI

If like me you decide to use the included "/projectname/images" folder to store your applications' images, you can change this line from the tutorial:

$model->image->saveAs('path/to/localFile');

To be this:

$model->image->saveAs(Yii::app()->basePath . '/../images/' . $model->image);
// As others have noted: $model->image at the end of the path is required,    // and is the filename of your image

The Yii::app()->basePath includes "/protected" at the end, and as the folder "images" is a sibling to "protected" so the /../ is necessary.

I'll also add that an easy way to display an uploaded image, would then be to open your view file, and use CHtml::image to generate tags for your Images with the necessary attributes, as follows:

<?php echo CHtml::image(Yii::app()->baseUrl . '/images/' . $data->image, 
$data->description,
   array("class" => "clickme", "title" => $data->title, "width"=>"300", "height"=>"220")); ?>

$data->description, and $data->title are from my Image.php model, and were perfect for the tags alt text and title, respectively.

#559 report it
skyer2000 at 2010/04/26 04:33pm
Defining enctype using CActiveForm

To define the enctype using CActiveForm, use the htmlOptions property:

$form=$this->beginWidget('CActiveForm', array( 'id'=>'paper-form', 'enableAjaxValidation'=>false, 'htmlOptions'=>array('enctype'=>'multipart/form-data') ));

#1460 report it
killermonk at 2009/07/28 01:25pm
More config Items

If you are interested in more config items, take a look at the code for the file (framework/validators/CFileValidator.php)

It gives you some small examples in the comments of how things can be used.

All of the public variables in the validator are options that can be set in the array.

Eg:

    public function rules()
    {
        return array(
            array('image', 'file',
                'types'=>'jpg, gif, png',
                'maxSize'=>1024 * 1024 * 50, // 50MB
                'tooLarge'=>'The file was larger than 50MB. Please upload a smaller file.',
            ),
        );
    }

Leave a comment

Please to leave your comment.

Write new article