Yii 1.1: How to upload a file using a model

64 followers

The Model

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', 'safe' => false),
        );
    }
}

You can add others validation parameters as described in CFileValidator. For instance, one can add a "maxSize" restriction (the PHP ini settings will of course prevail).

The Controller

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));
    }
}

CUploadedFile::saveAs() in one of the methods of CUploadedFile. You can also access directly to the file through its "tempName" property.

The View

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

$form = $this->beginWidget(
    'CActiveForm',
    array(
        'id' => 'upload-form',
        'enableAjaxValidation' => false,
        'htmlOptions' => array('enctype' => 'multipart/form-data'),
    )
);
// ...
echo $form->labelEx($model, 'image');
echo $form->fileField($model, 'image');
echo $form->error($model, 'image');
// ...
echo CHtml::submitButton('Submit');
$this->endWidget();

Another syntax is to use static calls in CHtml instead of CActiveForm. The result is the same as above.

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

Links

Total 7 comments

#20163 report it
Snake at 2018/01/30 01:29pm
PHP upload_max_filesize and post_max_size

If you are experiencing a situation where "nothing happens" after upload, depending on your settings, it is possible that PHP is killing it. Check the filesize you are trying to upload and make sure it is less than the value of upload_max_filesize in you php.ini. You can check that value on your PHP Info as well - whatever is easier. If that is your problem, assuming you have access to make changes to the php.ini file, just increase that value to what you need or want.

Depending on how big the file is, you may also need to increase the post_max_size value. PHP errors about this stuff should be in the apache error log, but will not generally show up in the Yii application log.

Hope this helps someone.

#18074 report it
Larry Jr. at 2014/09/04 11:14am
My code is not uploading the file

Please Help! It's not working for me, after submitting the form nothing happened, here's my printscreen: printscreen

This is my action rule:

public function rules()
{
    return array(
        //...
                array('filename', 'file', 'types'=>'jpg, gif, png, pdf'),
        //...
    );
}

Here's my controller:

public function actionCreate()
{
    $model=new Image;
 
    if(isset($_POST['Image']))
    {
        $model->attributes=$_POST['Image'];
                $tempSave=CUploadedFile::getInstance($model, 'filename');
        if($model->save())
                           $tempSave->saveAs(Yii::app()->basePath .
                           '/../productimages/' . $model->id.'.jpg');
        $this->redirect(array('view','id'=>$model->id));
    }
 
    $this->render('create',array('model'=>$model));
}

And for the view (_form.php) I have this:

<?php $form = $this->beginWidget(
             'CActiveForm',
             array(
                 'id' => 'upload-form',
                 'enableAjaxValidation' => false,
                 'htmlOptions' => array('enctype' => 'multipart/form-data'),
             )
     ); ?>
 
  <div class="row">
    <?php echo $form->labelEx($model,'title'); ?>
    <?php echo $form->textField($model,'title',array(
                                                 'size'=>45,
                                                 'maxlength'=>45
    )); ?>
    <?php echo $form->error($model,'title'); ?>
  </div>
 
  <div class="row">
    <?php echo $form->labelEx($model,'filename'); ?>
    <?php echo $form->fileField($model,'filename',array(
                                                   'size'=>45,
                                                   'maxlength'=>45
    )); ?>
    <?php echo $form->error($model,'filename'); ?>
  </div>
 
  <div class="row buttons">
    <?php //echo CHtml::submitButton('Submit'); ?>
    <?php echo CHtml::submitButton($model->isNewRecord ? 'Upload' : 'Save'); ?>
  </div>
<?php $this->endWidget(); ?><!--CActiveForm widget-->
#15918 report it
Kostas Apazidis (KonApaz) at 2013/12/29 07:52am
Re: How to validate a local file (removed question)

File Validation cannot be used before file uploaded on the server.

Instead of that, you could make javascript validation.

See the relative wiki http://www.yiiframework.com/wiki/598/clientvalidation-for-files-modern-browsers/

#15745 report it
Gerhard Liebenberg at 2013/12/11 04:42pm
$model->image = null

Tip: My $model->image stayed null, until I changed my json submit (with ($form).serialize()) back to a normal submit.

Also check that you have 'htmlOptions' => array('enctype' => 'multipart/form-data'), when you declare the active form - otherwise $image will stay null.

#15573 report it
Nacesprin at 2013/11/22 11:13am
Add attribute 'safe'=>true to rules()

You need to add the 'safe'=>true property to array('image', 'file', 'types'=>'xxxx', 'safe'=>true), or you'll get "Failed to set unsafe attribute 'image' ":

http://www.yiiframework.com/forum/index.php/topic/26456-failed-to-set-unsafe-attribute-file/

#11695 report it
CedSha at 2013/01/28 03:47am
Validation (Response at @outrage )

I had the same problem, after investigation I have solved that way :

...
$model->attributes=$_POST['MyForm'];
$model->filename=CUploadedFile::getInstance($model,'filename');
if ($model->validate()){
    $model->image->saveAs('path/to/localFile');

I think if your model is not an instance of CActiveRecord, then you wont be able to do the

if($model->save())

and I believe the validation step is made there. So you have to explicitly test the validation.

#10909 report it
GusDeCooL at 2012/12/02 01:23pm
File Handling Validation

Remember to check your CUploadFile, if null don't do saveAs or you will get an error

Here is sample of my code

public function actionCreate() {
        $this->layout = '//layouts/column1';
        $this->pageTitle = 'Create post for '.$this->pageTitle;
        $model = new Article;
 
        // Uncomment the following line if AJAX validation is needed
        // $this->performAjaxValidation($model);
 
        if (isset($_POST['Article'])) {
            $model->attributes = $_POST['Article'];
            $model->created = date('Y:m:d H:i:s');
            $model->group = $this->articleGroup;
            $model->fk_user_id = Yii::app()->user->id;
 
            // file handling
            $imageUploadFile = CUploadedFile::getInstance($model, 'image');
            if($imageUploadFile !== null){ // only do if file is really uploaded
                $imageFileName = mktime().$imageUploadFile->name;
                $model->image = $imageFileName;
            }           
 
            $voiceUploadFile = CUploadedFile::getInstance($model, 'voice_note');
            if($voiceUploadFile !== null) {
                $voiceFileName = mktime().$voiceUploadFile->name;
                $model->voice_note = $voiceFileName;
            }
 
 
            if ($model->save()){
                if($imageUploadFile !== null) // validate to save file
                    $imageUploadFile->saveAs(Article::FOLDER_IMAGE.$imageFileName);
 
                if($voiceUploadFile !== null)
                    $voiceUploadFile->saveAs(Article::FOLDER_VOICE.$voiceFileName);
 
                $this->redirect(array('view', 'id' => $model->id));
            }   
        }
 
        $this->render('//article/create', array(
            'model' => $model,
        ));
    }

Leave a comment

Please to leave your comment.

Write new article
  • Written by: qiang
  • Updated by: samdark
  • Category: Tutorials
  • Yii Version: 1.1
  • Votes: +86 / -7
  • Viewed: 453,835 times
  • Created on: Feb 4, 2009
  • Last updated: May 27, 2015
  • Tags: File upload