Yii 1.1: Uploading multiple images with CMultiFileUpload

39 followers
  • "The documentation for CMultiFileUpload isn't clear!"

  • "I don't know where the uploaded files went!"

  • "How can I save those files I uploaded in the right directory!"

  • "!@!##!!!!"

I understand your pain.

I went through a weeks worth of frustration that was unnecessary, so for your benefit, here are the steps towards the uploading of images via CMultiFileUpload so you can focus on the more important thing: your actual work.

  • Database - a user table, and a picture table, with the picture table linking (via a foreign key) back to the user table. More simplified versions (just uploading straight to a picture table) can be easily discerned via this specialized example.
  • Relations - So, given the above assumption, through the 'relations' function that gii (for example) auto-creates for you, you will be able to access your pictures like so: $model->pictures

View

In _form.php: - You have to add "multi-part/form-data" to your _form.php file, by two methods: either add the following modification to your header

<?php $form=$this->beginWidget('CActiveForm', array(
    'id'=>'topic-form',
    'enableAjaxValidation'=>false,
    'htmlOptions' => array('enctype' => 'multipart/form-data'), // ADD THIS
)); ?>

or this way, before your use of CMultiFileUpload

<?php echo CHtml::form('','post',array('enctype'=>'multipart/form-data')); ?>

The actual CMultiFileUpload implementation is this way:

$this->widget('CMultiFileUpload', array(
                'name' => 'images',
                'accept' => 'jpeg|jpg|gif|png', // useful for verifying files
                'duplicate' => 'Duplicate file!', // useful, i think
                'denied' => 'Invalid file type', // useful, i think
            ));

Controller

Algorithm:

  1. load the model in question

  2. check if the model is set

  3. get your uploaded images

  4. save each image in the appropriate place on your server

  5. create new instantiation of your picture model

  6. save that instantiation

  7. save the rest of the data you used in your form

  8. onto the next headache

Before we go on, both your actionCreate() and actionUpdate() methods need to access the folder where you are saving your image. How you handle the OOP design is up to you, but here's the code to create the directory, as well as creating it if it wasn't done already:

// make the directory to store the pic:
if(!is_dir(Yii::getPathOfAlias('webroot').'/images/ADD YOUR PATH HERE!/'. $model->name)) {
   mkdir(Yii::getPathOfAlias('webroot').'/images/ADD YOUR PATH HERE!/'. $model->name))
   chmod(Yii::getPathOfAlias('webroot').'/images/ADD YOUR PATH HERE!/'. $model->name)), 0755); 
   // the default implementation makes it under 777 permission, which you could possibly change recursively before deployment, but here's less of a headache in case you don't
}

Now in your actionUpdate(), or actionCreate():

$model=$this->loadModel($id);
 
        // Uncomment the following line if AJAX validation is needed
        //$this->performAjaxValidation($model);
 
        if(isset($_POST['Topic'])) {
 
            $model->attributes=$_POST['Topic'];
 
            // THIS is how you capture those uploaded images: remember that in your CMultiFile widget, you set 'name' => 'images'
            $images = CUploadedFile::getInstancesByName('images');
 
            // proceed if the images have been set
            if (isset($images) && count($images) > 0) {
 
                // go through each uploaded image
                foreach ($images as $image => $pic) {
                    echo $pic->name.'<br />';
                    if ($pic->saveAs(Yii::getPathOfAlias('webroot').'/images/ADD YOUR PATH HERE!/'.$pic->name)) {
                        // add it to the main model now
                        $img_add = new Picture();
                        $img_add->filename = $pic->name; //it might be $img_add->name for you, filename is just what I chose to call it in my model
                        $img_add->topic_id = $model->id; // this links your picture model to the main model (like your user, or profile model)
 
                        $img_add->save(); // DONE
                    }
                    else
                        // handle the errors here, if you want
                }
 
                // save the rest of your information from the form
                if ($model->save()) {
                    $this->redirect(array('view','id'=>$model->id));
                }
            }
        }
 
        $this->render('update',array('model'=>$model,));

Obviously, you have to handle the errors, but that's up to you (I haven't coded that yet). However, now you have the files uploaded to your model, and you can play around with it

Hat-tip: Wiseon3 caught a copy/paste error of mine:

"if ($pic->saveAs(Yii::getPathOfAlias('webroot').'/images/ADD YOUR PATH HERE!/'. $model->name)) {
               // add it to the main model now"

has been updated to

if ($pic->saveAs(Yii::getPathOfAlias('webroot').'/images/ADD YOUR PATH HERE!/'. $pic->name)) {
                        // add it to the main model now

The main code has been updated to reflect this change. Thanks

Total 16 comments

#16832 report it
SivaramAntony at 2014/04/01 11:02am
CMultiFileUpload

How to update max value dynamically in CMultiFileUpload, please if any one know means tell me.

#16780 report it
amanchandel at 2014/03/27 03:12am
cant send more than one value to db

my controller:

if(isset($images) && count($images)> 0) {

         foreach ($images as $image=>$pic)
                {   
              //
          if (
                  $pic->saveAs(Yii::getPathOfAlias('webroot').'/uploads/'.$model->location_name.'/'.$pic->name))   { 
             $model->save();

              $model->image = $pic;
                $model->types =$pic->type;
                $model->size =$pic->size;
                $model->setIsNewRecord(true);

                 }
            }
            }

                 if($model->save())
            $this->redirect(array('view','id'=>$model->location_id)) ;

             }
#16778 report it
amanchandel at 2014/03/27 03:07am
multiple upload

Cant save all value in db

if(isset($images) && count($images)> 0) {

         foreach ($images as $image=>$pic)
                {   
              //
          if (
                  $pic->saveAs(Yii::getPathOfAlias('webroot').'/uploads/'.$model->location_name.'/'.$pic->name))   { 
             $model->save();

              $model->image = $pic;
                $model->types =$pic->type;
                $model->size =$pic->size;
                $model->setIsNewRecord(true);
                echo "aman";
                 }
            }
            }

                if($modelaman->save())
                 if($model->save())
            $this->redirect(array('view','id'=>$model->location_id)) ;

             }
#15509 report it
joepages at 2013/11/16 09:51pm
Having trouble saving the files

Hi guys! I'm having troubles saving the files I just uploaded. The problem is that I click to upload the files, it shows that the files has been taken and when I click save it doesn't put them into de local file I'm saying...

My controller code is:

public function actionCreate()
    {
        $model=new Damas;
 
 
 
        // Uncomment the following line if AJAX validation is needed
        $this->performAjaxValidation($model);
 
        $type = isset($_GET['type']) ? $_GET['type'] : 'post';
 
        if(isset($_POST['Damas'])) {
            $model->attributes=$_POST['Damas'];
 
 
                $photos = CUploadedFile::getInstancesByName('photos');
 
                if (isset($photos) && count($photos) > 0) {
                    foreach ($photos as $image => $pic){
                        echo $pic->name.'<br />';
                        if ($pic->saveAs(Yii::getPathOfAlias('webroot').'/photos/damas/'.$pic->name)) {
                            $img_add = new Photo();
                            $img_add->filename = $pic->name;
                            $img_add->topic_id = $model->id;
                            $img_add->save();
                        } else {
                            echo 'existe algun error';
                        }
                    }
                }
            //termina la carga de imagenes
 
            if($model->save())
                $this->redirect(array('view','id'=>$model->id));
        }
 
        $this->render('create',array('model'=>$model,));
    }

[/php]

And my _form code is:

$this->widget('CMultiFileUpload', array(
     'model'=>$model,
     'attribute'=>'photos',
     'accept'=>'jpg|gif|png',
     'options'=>array(
        // 'onFileSelect'=>'function(e, v, m){ alert("onFileSelect - "+v) }',
        // 'afterFileSelect'=>'function(e, v, m){ alert("afterFileSelect - "+v) }',
        // 'onFileAppend'=>'function(e, v, m){ alert("onFileAppend - "+v) }',
        // 'afterFileAppend'=>'function(e, v, m){ alert("afterFileAppend - "+v) }',
        // 'onFileRemove'=>'function(e, v, m){ alert("onFileRemove - "+v) }',
        // 'afterFileRemove'=>'function(e, v, m){ alert("afterFileRemove - "+v) }',
     ),
     'denied'=>'File is not allowed',
     'max'=>10, // max 10 files
 
 
  ));
?>

[/php]

Please help me guys!

#14921 report it
fortinero at 2013/09/21 06:03pm
insert field for each image

First of all sorry for my english. I'm traing to insert a field for each image.

In the beggining I try to use xupload, it works nice, but i think that if i can do it without this extension is better becouse when i try to make multiple uploads fields in the same form, it was a problem and i loose control of the code. Then i try to use de jqrelcopy to create a multiple upload inserting a CHTM::filefield in each repeteable field, but i cant take the image Has someone find a good solution for this problem. I think is elemntaly.

I like to much yii, but i see that working with image with this framework is a problem.

Thanks H

#12921 report it
YiibieJeebi at 2013/04/20 01:24pm
select multiple

@Temir

You can select multiple files by adding this to the widget array

'htmlOptions' => array( 'multiple' => 'multiple', ),

#12165 report it
Manoj M at 2013/03/03 07:06am
How To Select Multiple Files

I need to select Multiple file at once, but this one doesnt allow, does anyone know how to add multi select to this widget..

#11337 report it
aep at 2013/01/06 09:38pm
Failed to sava to database

Dear all

I need some help immediately, i have try CMultiFileUpload to upload multiple file into my database, but the problem is the file is store into directory but the database still empty, does anyone know why this happen?

herewith my form source:

<?php echo $form->labelEx($model,'attachment'); ?>
<?php $this->widget('CMultiFileUpload', array( 'name' => 'attachment', 'accept' => 'jpeg|jpg|gif|png|pdf|doc|docx|xlx|xlsx|zip|rar', 'duplicate' => 'Duplicate file!', 'remove'=>Yii::t('ui','Remove <--'), 'denied' => 'File Is Not Allowed, Upload Only: jpeg,jpg,gif,png,pdf,doc,docx,xlx,xlsx,zip,rar', ));?> <?php echo $form->error($model,'attachment'); ?>

my model source:

array('attachment', 'file', 'types'=>'jpeg,jpg,gif,png,pdf,doc,docx,xlx,xlsx,zip,rar,rtf,ppt,pptx,txt', 'allowEmpty'=>true, 'on'=>'insert,update'), array('title, attachment', 'length', 'max'=>255, 'on'=>'insert,update'),

and my controller source:

public function actionCreate() {

$model=new Content;

// Uncomment the following line if AJAX validation is needed // $this->performAjaxValidation($model);

if(isset($_POST['Content'])) { $model->attributes=$_POST['Content']; $images = CUploadedFile::getInstancesByName('attachment'); if(isset($images) && count($images) > 0) { foreach ($images as $i=>$ii) { //echo $ii ->name. '
'; if ($ii->saveAs(Yii::getPathOfAlias('webroot').'/images/'.$ii->name)) { $img_add = new Content(); $img_add->attachment = $ii->name;
//$img_add->topic_id = $model->idpropinsi; $img_add->save(); } else $img_add = new Content(); $img_add->attachment = $ii->name;
//$img_add->topic_id = $model->idpropinsi; $img_add->save(); //}

if($model->save()) { $this->redirect(array('view','id'=>$model->id));

} } } } $this->render('create',array( 'model'=>$model, ));

}

Somebody help me please, today is my deadline for my homework

#10655 report it
Milind R at 2012/11/12 01:17am
File field : possible pitfall

Assigning the filename field with the name of the CUploadedFile object instance resulted in an error stating "filename cannot be blank". This is assuming you used the file validator in the model (conspicuously missing from the article, can someone add the model code too, for reference?)

What fixed my problem was to assign the object itself to the field.

$img_add->filename = $pic;

instead of

$img_add->filename = $pic->name;

Though I am not sure about the nature of the file attribute of a model (the DB table shows the filename). Someone having a better idea please PM me and update this article.

#9364 report it
Temir at 2012/08/07 02:49am
multiple="multiple"

how to select multiple images at once with

<input type='file' multiple="multiple">

?

I mean is there any option or is it possible to upgrade this widget?

#8776 report it
avner at 2012/06/26 07:14am
Re: Not working if i declare model and attribute

Have you tried getInstances($model,'filename') instead?

#7064 report it
Yureshwar Ravuri at 2012/02/22 02:34am
Not working if i declare model and attribute

Hi,

Here is the code for my form

<?php 
                $this->widget('CMultiFileUpload', array(
                'model' => '$model2',
                //'name' => 'files',
                'attribute' => 'filename',
                'accept' => 'jpeg|jpg|gif|png', // useful for verifying files
                'duplicate' => 'Duplicate file!', // useful, i think
                'denied' => 'Invalid file type', // useful, i think
            ));
            ?>

My controller for actionCreate i have included model2 while rendering the form.

$model2=new Images
if(isset($_POST['Images'])
{
  $model2->attributes=$_POST['Images'];
}

It gives me error like this when i submit the form.

Undefined Index Images

And if i comment the

if(isset($_POST['Images'])
{
  $model2->attributes=$_POST['Images'];
}

and continuing to the rest of the like this

$images=CUploadedFile::getInstancesByName($model2,'filename');

It gives me this error

strlen($name) expects string object given.

Can anyone help me how to handle through models.

#5208 report it
pligor at 2011/09/22 05:40am
Validator

At first I thought it would need a custom validator but finally the 'file' validator does the job.

If you want to upload multiple files then you MUST SET maxFiles parameter.

For example for an attribute named 'files' a rule would look like this:

array(
                'files',
                'file',
                'allowEmpty' => false,
                'maxFiles' => 14,
                //'tooMany' => 'some error message',
                'maxSize' => 10*(1024*1024),    //10MB
                //'tooLarge' => 'some error message',
                'minSize' => 1024,  //1KB
                //'tooSmall' => 'some error message',
                //'types' => $this->types,  //extension names separated by space or comma
                //'wrongType' => 'some error message',
            ),

As you can see I commented out the types attribute because this is already checked from CMultiFileUpload ;)

Without setting maxFiles I would get an error at validation that the 'files' attribute is blank!

#4545 report it
dRock at 2011/07/19 07:40am
If $images is coming up empty

You can also do:

$images = CUploadedFile::getInstances($model,'images');
#4099 report it
zealotous at 2011/06/06 01:16am
Advice

Don't forget to change post_max_size, upload_max_filesize parameters in you php.ini. There is can be problems with big files uploading.

#php.ini
post_max_size = 16M
upload_max_filesize = 16M
#3517 report it
Wiseon3 at 2011/04/17 05:23am
Correction image name

Shouldn't it be $pic->name in the $pic->saveAs() function, instead of $model->name?

So instead of

if ($pic->saveAs(Yii::getPathOfAlias('webroot').'/images/ADD YOUR PATH HERE!/'.$model->name))

it would be

if ($pic->saveAs(Yii::getPathOfAlias('webroot').'/images/ADD YOUR PATH HERE!/'.$pic->name))

Leave a comment

Please to leave your comment.

Write new article