Difference between #2 and #3 of How to use YiiBooster TbFileUpload widget

unchanged
Title
How to use YiiBooster TbFileUpload widget
unchanged
Category
How-tos
unchanged
Tags
YiiBooster, How to, File upload
changed
Content
Introduction
------------ 
The following wiki is to explain how to make use of the TbFileUpload widget from
YiiBooster. I have received a couple of requests and I thought was worth writing
a wiki for it. 

Usage
-----
### Preparation 
First, we need to make sure we have a folder with write permissions, that will
be the place where we are going to save our uploaded files. 

I normally create a `files` folder and I allocate it within my `www` one, that
is where I keep my css, js, images files. So, even though you can place it where
ever you wish and for the sake of the example, I will use the `files` folder
name.

I also assume that you have configured a path alias that references the `files`
folder. On this example, the path alias is `frontend.www.files`. 

### Note   
* This demo only works if the MyModel class already includes the function
getImageUrl($img_type=null). If not, comment the 2 lines inside the data array,
where 'url' and 'thumbnail_url' are defined, to make the demo work  
* If the MyModel has a different name, it needs to be replaced 1-2 times inside
the upload action  
* The url where we are going to upload our files => upload action  

_Thanks [Don Felipe](http://www.yiiframework.com/user/9450/)_  

### Setup your model
The way you handle validation on the server is up to you, the configuration I am
going to provide now is just an example. 

We are going to add one extra attribute to the model `picture`, which is going
to hold any $_FILE type resource uploaded and validated when model is on
`upload` scenario.
~~~
[php]
class MyModel extends CActiveRecord {
// ... more code here
/**
* This is the attribute holding the uploaded picture
* @var CUploadedFile
*/
public $picture;
// ... more code

/**
* @return array validation rules for model attributes.
*/
public function rules()
{
  return array(
    // ... more rules here
    array('picture', 'length', 'max' => 255, 'tooLong' => '{attribute} is
too long (max {max} chars).', 'on' => 'upload'),
    array('picture', 'file', 'types' => 'jpg,jpeg,gif,png', 'maxSize' =>
1024 * 1024 * 2, 'tooLarge' => 'Size should be less then 2MB !!!', 'on' =>
'upload'),
    // ... more rules here
  );
}
~~~

### Configuring the Widget
To render the widget on your view is quite straightforward, the are a couple of
things very important to configure:   

* the url where we are going to upload our files   
* the file types we are going to accept and their maximum size
 
Now, lets render it:
~~~
[php]
<?php $this->widget('bootstrap.widgets.TbFileUpload', array(
    'url' => $this->createUrl("my/upload"),
    'model' => $model,
    'attribute' => 'picture', // see the attribute?
    'multiple' => true,
    'options' => array(
    'maxFileSize' => 2000000,
    'acceptFileTypes' => 'js:/(\.|\/)(gif|jpe?g|png)$/i',
))); ?>
~~~
#### Handling Upload
Everything is ready now but the controller. We have to configure the action that
will handle the upload process. Here you go, the upload action of our controller
-very, very basic - and not fully tested: 
~~~
[php]
class myController extends CController {
// ... more code here

/**
* Handles resource upload
* @throws CHttpException
*/
public function actionUpload()
{
    header('Vary: Accept');
    if (isset($_SERVER['HTTP_ACCEPT']) && 
        (strpos($_SERVER['HTTP_ACCEPT'], 'application/json') !== false))
    {
        header('Content-type: application/json');
    } else {
        header('Content-type: text/plain');
    }
    $data = array();

    $model = new MyModel('upload');
    $model->picture = CUploadedFile::getInstance($model, 'picture');
    if ($model->picture !== null  &&
$model->validate(array('picture')))$model->validate(array('picture'))
    {
        $model->picture->saveAs(
       
Yii::getPathOfAlias('frontend.www.files').'/'.$model->picture->name);
        $model->file_name = $model->picture->name;
        // save picture name
        if( $model->save())
        {
            // return data to the fileuploader
            $data[] = array(
                'name' => $model->picture->name,
                'type' => $model->picture->type,
                'size' => $model->picture->size,
                // we need to return the place where our image has been saved
                'url' => $model->getImageUrl(), // Should we add a helper
method?
                // we need to provide a thumbnail url to display on the list
                // after upload. Again, the helper method now getting thumbnail.
                'thumbnail_url' =>
$model->getImageUrl(MyModel::IMG_THUMBNAIL),
                // we need to include the action that is going to delete the
picture
                // if we want to after loading 
                'delete_url' => $this->createUrl('my/delete', 
                    array('id' => $model->id, 'method' => 'uploader')),
                'delete_type' => 'POST');
        } else {
            $data[] = array('error' => 'Unable to save model after saving
picture');
        }
    } else {
        if ($model->hasErrors('picture'))
        {
            $data[] = array('error', $model->getErrors('picture'));
        } else {
            throw new CHttpException(500, "Could not upload file ".   
 CHtml::errorSummary($model));
        }
    }
    // JQuery File Upload expects JSON data
    echo json_encode($data);
}

// .... more code here 

} // end of controller
~~~
Resources
------------------
- [http://blueimp.github.com/jQuery-File-Upload/
](http://blueimp.github.com/jQuery-File-Upload/  "")

Final Notes
------------------
The upload action example was not really tested, if any of you had problems with
it, please submit your changes to the [YiiBooster Forum
Topic](http://www.yiiframework.com/forum/index.php/topic/36258-yiibooster/). Any
help would be highly appreciated to improve this wiki.