Upload de arquivo com Yii framework

14/08/2013

Programo com Yii framework há mais de um ano, e considero um ótimo framework. Porém, algumas pessoas realmente não gostam da forma como o framework é documentado, em forma de api. De fato, alguns recursos não são bem exemplificado.

Em vista disto, resolvi escrever uma série de posts sobre recursos do framework que são bastantes utilizados. Neste post, mostrarei como realizar upload de arquivo utilizando o compoente CUploadedFile.

Primeiro, vamos considerar um modelo de Photo, como exemplo do recurso, contendo os atributos image e legend. No controller criaremos uma instância da classe CUploadedFile, informando como parâmetro o modelo de Photo e o nome do campo de seleção do arquivo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class PhotoController extends CController{
    public function actionCreate(){
        $model = new Photo;
        if(isset($_POST['Photo'])){
            $model->attributes = $_POST['Photo'];
            $model->image = CUploadedFile::getInstance($model,'image');
            $saveAs = Yii::getPathOfAlias('photoPath').'/'.$model->image->name;
            if($model->save()){
                $model->image->saveAs($saveAs);
            }
        }
        $this->render('create', array('model' => $model));
    }
}

Na linha 9, chamamos o método saveAs() que indica o local onde o arquivo será salvo. Nele, definimos o local através do setPathOfAlias que deve ser definido no config/main.php

Devemos observar que esta função irá sobrescrever o arquivo, caso seja enviado dois com mesmo nome. Para evitar isso, você pode renomear o arquivo original para um único, utilizando uma hash ou concatenando com um timestamp, por exemplo.

Caso queira preservar o nome original enviado pelo usuário, você pode utilizar a função file_exists e tratar o nome do arquivo somente se já existir um com mesmo nome em seu servidor.

View

Na view, precisamos definir duas coisas: o atributo enctype na tag <form> e o campo tipo files no formulário. Assim, teremos:

1
2
3
4
5
6
7
8
9
10
11
12
<?php  
$form = $this->beginWidget('CActiveForm', array(
	'id'=>'photo-form',
        'htmlOptions' => array('enctype' => 'multipart/form-data'),
)); 
 
echo $form->labelEx($model,'image');
echo $form->fileField($model,'image');
echo $form->error($model,'image');
 
$this->endWidget();
?>

Model

Em nosso exemplo, devemos validar para que somente arquivos de imagem sejam enviados para o servidor. No caso, definimos a regra em nosso modelo.

1
2
3
4
5
public function rules(){
    return array(
        array('image', 'file', 'types'=>'jpg, gif, png', 'maxSize'=>1024 * 1024 * 50),
    );
}

Outras validações podem ser adicionadas, baseada no CFileValidator.

É isso, galera. Espero que tenha ajudado. Qualquer dúvida deixe um comentário no post ou através do twitter @vinaocruz.

Abraço