Neste post irei demonstrar a regra de negócio por trás do SWFUpload, uma biblioteca javascript usada para controle de upload de arquivos no Browser utilizando o Flash. Ela controla o lado cliente enquanto o desenvolvedor a utiliza de uma forma extensível com a interface com o usuário. Em posts anteriores eu mostrei como esta interação pode ser feita com o jQuery, e muitas dúvidas surgiram de como receber os arquivos no lado servidor. Irei demonstrar utilizando o PHP com a framework CakePHP em como manipular os arquivos.

Foi utilizada o componente do cakePHP para este propósito.

Primeiramente, para acessar os arquivos no server-side utilizando PHP, temos basicamente o seguinte código:

[sourcecode language=”php”]

$_FILE[‘Filedata’];

[/sourcecode]

Sim, é a mesma forma como é recebido arquivos no server utilizando o input do tipo file. Esta biblioteca é totalmente não-obstrusiva. Você trata da mesma forma como trataria se o Javascript não estivesse habilitado. A diferença aqui é que ele faz a chamada para o script server-side a cada interação de upload, permitindo que seja feito múltiplos e com controles que não são possíveis com o upload padrão do formulário, como barra de progresso e tamanho do arquivo.

Para realizar regras mais elaboradas, utilizei um componente do SWFUploade para CakePHP. Ele possui métodos que facilitam a manipulação dos arquivos enviados para o server. Irei aproveitar para explicar um pouco da arquitetura MVC (Model, View, Controller) e do funcionamento do cakePHP.

O código do back-end segue abaixo:

[sourcecode language=”php”]

function addFoto($id) {

$this->Portfolio->id = $id;
$this->set(‘portfolioId’, $this->Portfolio->read());
$cliente = $this->Portfolio->field(‘cliente’,”where id=’$id'”);
if (isset($this->params[‘form’][‘Filedata’])) {

$minuscula = strtolower($cliente);
$cliente_filtrado = strtr($minuscula,’áéíóúêçã ‘,’aeioueca_’);

// upload the file
// use these to configure the upload path, web path, and overwrite settings if necessary
$this->SwfUpload->uploadpath = ‘img’ . DS . ‘upload’. DS. $cliente_filtrado . DS;
$this->SwfUpload->webpath = ‘/img/upload/’.$cliente_filtrado.’/’;
chmod(‘/img/upload/’.$cliente_filtrado,777);
$caminho_db = explode(“/”,$this->SwfUpload->webpath);
$this->SwfUpload->overwrite = true;

//by default, SwfUploadComponent does NOT overwrite files

if ($this->SwfUpload->upload()) {

// save the file to the db, or do whateve ryou want to do with the data
$this->params[‘form’][‘Filedata’][‘name’] = $this->SwfUpload->filename;
$this->params[‘form’][‘Filedata’][‘path’] = $this->SwfUpload->webpath;
$this->params[‘form’][‘Filedata’][‘fspath’] = $this->SwfUpload->uploadpath.$this->SwfUpload->filename;
$this->data[‘Foto’][‘url’] = ‘/’.$caminho_db[2].’/’.$caminho_db[3].’/’.$this->SwfUpload->filename;
$this->data[‘Foto’][‘descricao’] = “”;
$this->data[‘Foto’][‘status’] = 0;
$this->data[‘Foto’][‘portfolio_id’] = $id;

if (!$this->Foto->save($this->data)){
$this->Session->setFlash(‘Database save failed’);

} else {
$this->Session->setFlash(‘File Uploaded: ‘ . $this->SwfUpload->filename . ‘; Database id is ‘ . $this->Foto->getLastInsertId() . ‘.’);

}
} else {
$this->Session->setFlash($this->SwfUpload->errorMessage);

}
}

}//fim addFoto

[/sourcecode]

Inicialmente, toda a implementação fica dentro de uma função addFoto, pois neste caso o SWFUpload foi usado para este propósito. Esta função fica dentro de uma classe, o controller, que estende a classe App Controller. Para quem não tem familiaridade, parece meio estranho, mas a arquitetura MVC é bastante intuitiva.

O método addFoto fica no controller Admin, pois neste caso o upload de fotos foi usado para um CMS. Neste gerenciador o cliente pode enviar fotos e assim elas podem ser visualizadas e descritas em uma outra página. Cada controller pode ter vários actions, que seria os métodos da classe. Essa estrutura também é aplicada a url, sendo assim, o action do form onde o upload é feito pode facilmente ser http://www.dominio.com/admin/addFoto.

Por trás do controller e actions, existe a abstração com o banco de dados, em que é feito nesta framework e em muitas outras MVC o mapeamento automático do Banco de dados em objeto. Assim, existe um model Portfolio que representa uma tabela no banco em que pode ser acessado seus campos correspondentes(linha 3).

Para completar o trio MVC, falta somente a View. Na linha 4 o controller atribuiu uma variável para ser acessada pela view. A view é simplesmente o template HTML, que no MVC é estritamente usado somente para exibição de dados para o usuário. Neste caso, não realizamos regra de negócio na view, deixando esta tarefa com o controller. Assim a view poderá acessar normalmente a variável passada, que pode ser string, array ou até um objeto.

O Componente é uma classe usada para realizar tarefas no controller com intuito de reaproveitar regra de negócios. Para a view, existe os Helpers, que executam lógicas como por exemplo gerar formulários.

Na linha 13 a 17 atribui algumas propriedades do componente SWFUpload para escolher o caminho a ser enviado o arquivo. Na linha 21, o método de envio foi chamado em uma estrutura condicional, pois este método retorna booleano com o status do upload realizado.

O $this->params do CakePHP simplesmente é um atributo do Controller principal onde fica guardado todos os POST’s enviados pelo form, assim ele pode ler os dados do arquivo.

$this->data é um array que fica no formato do [Model][campo] para ser preenchido para que em uma única chamada do método Save as informações no banco são corretamente salvos.

O restante da implementação prepara a formatação do arquivo para ser inserido no banco de dados com as referências corretas. Na linha 32 então os dados são salvos no banco de dados.

Infelizmente não posso postar este exemplo devido a ética profissional (por este lado retiro o infelizmente, ele foi posto pensando na facilidade para os leitores, pois um exemplo vale mais que mil palavras). Mas espero que tenha servido de referência e um caminho para os que estão utilizando esta ferramenta ou que não conheciam os poderes que a arquitetura MVC pode oferecer.

Algumas referências:

5 Replies to “SWFUpload – Server-side”

  1. Muito bom o artigo Alexandre, parabéns!

    Eu tenho utilizado SWFUpload em todos os projetos que tem upload, porém hoje eu dei de cara com um problema que antes não tinha visto.
    Quando uso SWFUpload em HTTPS eu recebo Error #2038. Alguma idéia do que possa ser?

    Abraços, até mais!

    1. Então, este erro acontece pois houve uma exceção após o arquivo ter sido enviado para o servidor, porém ele não é mostrado no console pois a instrução de upload é chamada pelo swfupload, procure na sua aplicação, se for um framework, procure no log, procure qualquer possibilidade de erro e verá que ele acontece. No meu caso eu estou utilizando o web2py e encontrei o motivo na sessão de erros do framework, mesmo ele não sendo mostrado na interface da aplicação ou console do browser, ou seja, o erro é individual para cada aplicação, não existe uma solução única, e o problema provavelmente não é com o SwfUpload.

  2. Olá Alexandre,

    É realmente falando em upload múltiplos seu site é a primeira referência.
    Venho ultilizando seu sistema de múliplos uploads desde 2007, hj depararei com um problema, quando instalei WinXP Pro SP3, simplesmente quando clico em “Procurar” nada aconcete, vc passa por esse problema também? Inclusive isso acontece também quando utilizo seu endereço de demonstração http://www.alexandremagno.net/blog/wp-content/uploads/swfupload/index.htm.

    Sdç David.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *