Como fazer um upload de arquivo no Symfony 1.1

Como falei no post anterior, o symfony-pt está ajudando na tradução do CookBook do symfony 1.1. Então, estarei postando todos os artigos traduzidos com os respectivo nome de quem os traduziu. Hoje, irei postar um artigo traduzido por mim, e é sobre como fazer um upload no symfony 1.1.

Vale lembrar que todos esses artigos estarão na documentação do symfony.

h2. Visão Geral

Muitas vezes backends e aplicações colaborativas exigem que os usuários façam upload de arquivos. Com algumas linhas de código, o symfony toma conta de tudo: renomeia o arquivo, move para o diretório de upload etc. E o usuário do admin generator também tem acesso ao novo helper que reduz a implementação para uma configuração simples.

h2. Upload de arquivo regular

O upload de um arquivo requer um form em um template, e uma action para lidar com ele. No template, use o helper ‘input_file_tag()’ no form declarando-o como ‘multipart=true’:

echo form_tag(‘media/upload’, ‘multipart=true’)
echo input_file_tag(‘file’)
echo submit_tag(‘Send’)

Irá gerar o código HTML:

<form method="post" enctype="multipart/form-data" action="media/upload">
<input name="file" id="file" type="file" />
<input name="commit" value="Send" type="submit" />
</form>

A action (‘media/upload’ no exemplo) move o arquivo para o diretório de upload:

public function executeUpload()    {
         $fileName = $this\->getRequest()\->getFileName(‘file’);
         $this–>getRequest()–>moveFile(‘file’, sfConfig::get(‘sf_upload_dir’) . ‘/’ . $fileName);
         $this->;redirect(‘media/show?filename=’.$fileName);
}

O parâmetro ‘sf_upload_dir’ detém o caminho absoluto no seu servidor, para onde o arquivo vai ser enviado. Para o projeto chamado ‘myproject’, normalmente é em ‘/home/production/myproject/web/upload/’. Você pode modificá-lo em ‘config/config.php’:

sfConfig::add(array(‘sf_upload_dir_name’  => $sf_upload_dir_name = ‘uploads’ , ‘sf_upload_dir’  => sfConfig::get(‘sf_root_dir’) . DIRECTORY_SEPARATOR . sfConfig::get(‘sf_web_dir_name’)  . DIRECTORY_SEPARATOR . $sf_upload_dir_name,));

*Nota*: Antes de mover um arquivo para o diretório de upload, você deve ‘limpar’ o nome do arquivo substituindo caracteres especiais para evitar problemas de arquivo do sistema. Além disso, você deve escapar o ‘$fileName’ antes de passá-lo como um pedido de parâmetro.
Para mostrar o arquivo enviado, use o parâmetro ‘sf_upload_dir_name’. Por exemplo, se o arquivo for uma imagem, o template ‘media/show’ ficará assim:


echo image_tag(‘/’.sfConfig::get(‘sf_upload_dir_name’) . ‘/’.$sf_params->get(‘filename’))

h2. Validação

Como inputs de texto normais, o file upload pode ser validado pelo symfony validator com o ‘sfFileValidator’. Mas lembre-se de colocar o parâmetro ‘file: true’ na declaração do validator abaixo de ‘names’. Por exemplo, o ‘validate/upload.yml’ do form anterior deve ser escrito assim:

   methods:
      post:               [file]
    names:
      file:
        required:         Yes
        required_msg:     Please upload a file
        validators:       myFileValidator
        file:             true
    myFileValidator:
      class:              sfFileValidator
      param:
        mime_types:
          – ‘image/jpeg’
          – ‘image/png’
          – ‘image/x-png’
          – ‘image/pjpeg’
        mime_types_error: Only PNG and JPEG images are allowed
        max_size:         512000
        max_size_error:   Max size is 512Kb

*Nota*: Devido a inconsistências entre o Internet Explorer e outros navegadores, você terá que usar mime-types específicos para o IE.
O ‘sfFileValidator’ pode validar o tipo de arquivo enviado (você pode especificar um array de mime-types) e seu tamanho (você pode especificar o tamanho mínimo e o máximo).

h2. Thumbnails

Se você fizer uploades de imagem, talvez você precise criar thumbnails para cada arquivo enviado. Nesse caso, o ‘sfThumbnail’ plugin pode lhe ser útil.
Primeiro, instale o plugin usando a linha de comando do symfony:

$ symfony plugin-install http://plugins.symfony-project.com/sfThumbnailPlugin
$ symfony cc

*Nota*: Se a biblioteca GD não está ativada, você terá que descomentar a linha relacionada em seu ‘php.ini’ e reiniciar seu servidor web para ativar as funções PHP.
Com o plugin instalado, você pode usá-lo através do objeto ‘sfThumbnail’. Por exemplo, para salvar um thumbnail com no máximo 150x150px ao mesmo tempo em que envia a imagem no exemplo acima, substitua a action ‘media/upload’ por:

public function executeUpload()    {
         $fileName = $this\->getRequest()\->getFileName(‘file’);
         $thumbnail = new sfThumbnail(150, 150);
         $thumbnail\->loadFile($this\->getRequest()\->getFilePath(‘file’));
         $thumbnail->save(sfConfig::get(‘sf_upload_dir’).‘/thumbnail/’ . $fileName, ‘image/png’);
         $this\->getRequest()\->moveFile(‘file’, sfConfig::get(‘sf_upload_dir’) . ‘/’ . $fileName);
         $this->redirect(‘media/show?filename=’.$fileName);
}

Não esqueça de criar o diretório ‘uploads/thumbnail’ antes de executar a action.

h2. Upload de arquivo no admin generator

Se o seu modelo de dados contém um campo para arquivos, e se sua administração é feita com o admin generator, você pode usar o helper ‘object_admin_input_file_tag()’. Ele faz tudo pra você com uma simples configuração.
Por exemplo, você tem a tabela ‘User’ com a coluna ‘photo’, o ‘generator.yml’ para o view do ‘edit’, pode ser configurado assim:

   edit:
      title:          User profile
      fields:
        photo:
          name:       User photo
          help:       max width 200px
          type:       admin_input_file_tag
          upload_dir: pictures/users
          params:     include_link=pictures/users include_remove=true
      display:        [name, email, photo]

O ‘upload_dir’ define o diretório de uploads (sob o diretório ‘uploads/’).
Se você incluir um parâmetro ‘include_link’, um link será adicionado ao arquivo enviado (isto é, se um arquivo de media for enviado). O texto do link é ‘[show file]‘ por padrão, a não ser que você especifique com o parâmetro ‘include_text’.

Se você incluir um ‘include_remove’, o helper mostrará um link para remover o arquivo quando clicado.

*Traduzido por Bernardo Dantas*