Como enviar um arquivo

Visão Geral

Backends e aplicativos de colaboração freqüentemente requer que os usuários enviem arquivos de dados ou de media. Com algumas linhas de código, symfony faz tudo que precisamos - renomeia o arquivo, move para o diretório, etc.E os usuários do gerador de admin têm também o acesso a um novo ajudante que reduza a execução a uma configuração simples.

Upload de arquivo regular

Enviar um arquivo requer um form em um template, e um action para ele. Para o template, use helper input_file_tag() em um form declarado como multipart:

    <?php echo form_tag('media/upload', 'multipart=true') ?>
      <?php echo input_file_tag('file') ?>
      <?php echo submit_tag('Send') ?>
    </form>

Isto resultara no seguinte código HTML:

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

O action (media/upload neste exemplo) move o arquivo do request para o diretório de upload:

 <?php
  ...
    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 seta o path absoluto, no seu servidor, onde os arquivos serão armazenados. Para um projeto chamado myproject, por padrão é /home/production/myproject/web/upload/. Você pode alterar isto facilmente em config/config.php:

  <?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 o arquivo do request para o diretório, você deve tratar o arquivo para substituir os caracteres especiais para evitar problema com o sistema de arquivos.

Para mostrar o arquivo enviado, use o parâmetro sf_upload_dir_name. Por exemplo, se o arquivo é uma imagem, o template media/show mostrara:

    ...
    <?php echo image_tag('/'.sfConfig::get('sf_upload_dir_name').'/'.$sf_params->get('filename')) ?>

Validação

Com entradas regulares de formulários, as Tag de upload da arquivo podem ser validados pelo [symfony validator](http://www.symfony-project.com/book/trunk/10-Forms#Validators), o sfFileValidator. Recorde apenas de colocar um file: true na declaração do validador na chave name. Para a instancia, o validate/upload.yml para o formulário precedente deve ser escrito como segue:

  methods:
      post:               [file]
      
    names:
      file:
        required:         Yes
        required_msg:     Por favor envie um arquivo
        validators:       myFileValidator
        file:             true
        
    myFileValidator:
      class:              sfFileValidator
      param:
        mime_types:       
          - 'image/jpeg'
          - 'image/png'
          - 'image/x-png'
          - 'image/pjpeg'        
        mime_types_error: Somente arquivos PNG e JPEG imagens são permitidas
        max_size:         512000
        max_size_error:   Tamanho máximo do é 512Kb

Nota: Devido às inconsistências entre o Internet Explorer e os outros browsers, vocÊ precisa usar o tipos IE-específicos do mime como regular.

O sfFileValidator pode validar o tipo de arquivo enviado (você pode especificar uma matriz de mime types) seu tamanho (você pode especificar o tamanho mínimo e máximo).

Thumbnails

Se você enviar imagens, você pode ter a necessidade de criar um thumbnails do arquivo. Neste caso, o [sfThumbnail plugin](http://www.symfony-project.com/trac/wiki/sfThumbnailPlugin) pode 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 livraria GD não estiver ativa, você deve descomentar a sua linha no php.ini e reiniciar o webserver para ativar as funções.

Com o plugin instalado, você pode usar o objeto sfThumbnail. Por exemplo, para conservar um thumbnail do tamanho máximo 150x150px ao mesmo tempo que a imagem é enviada, troque o media/upload action por:

  <?php
    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 se esqueça de criar o diretorio uploads/thumbnail/ antes de usar o action.

File upload com o admin generator

Se seu modelo dos dados contiver um campo para mídias, e se sua administração for usar o construtor [admin generator](http://www.symfony-project.com/book/trunk/14-Generators#Administration), você pode o helper de nome longo object_admin_input_upload_tag(). Isto faz tudo para você com apenas uma configuração simples.

Por exemplo, se você tem uma tabela user com uma coluna photo, o generator.yml para o edit view pode ser configurado com segue:

    edit:
      title:          Perfil do usuário 
      fields:
        photo:
          name:       Foto do Usuário
          help:       maximo com 200px
          type:       admin_input_file_tag
          upload_dir: pictures/users
          params:     include_link=pictures/users include_remove=true
      display:        [name, email, photo]

O chave upload_dir seta o diretório de upload (dentro do diretório uploads/).

Se você incluir o parâmetro include_link, um link será adicionado paro o arquivo enviado (isto é, se a mídia for enviada). O texto do link é '[show file]' por padrão - a menos que seja especificado um parâmetro include_text.

Se você incluir um parâmetro include_remove, o helper mostrará um link para permitir uma fácil remoção do arquivo quando clicado.