Carlos Gustavo (The Froskie) Internet, web, www…

2out/090

Download de arquivos com Adobe AIR

Em um projeto recente em Flex/AIR, um player em um thin client precisava tocar vídeos, áudios e imagens que vinham de uma central. Havia a necessidade de fazer isso offline para que não torrasse banda. Então precisei de uma classe que faria o download de um arquivo, vindo de uma URL, para dentro da pasta de armazenamento da aplicação (applicationStoreDirectory):

package 
{
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.ProgressEvent;
    import flash.filesystem.File;
    import flash.filesystem.FileMode;
    import flash.filesystem.FileStream;
    import flash.net.URLRequest;
    import flash.net.URLStream;
    import flash.utils.ByteArray;
 
 
    public class FileDownloader extends EventDispatcher
    {    
        // url do arquivo
        private var fileURL:String;
 
        // url stream do arquivo
        private var urlStream:URLStream;
 
        // file stream do arquivo
        private var fileStream:FileStream;
 
        // referencia fisica do arquivo completo
        private var fileRef:File;
 
        public function FileDownloader(){
 
            // inicia os streams
            urlStream = new URLStream();
            fileStream = new FileStream();
 
            // eventos da URL
            urlStream.addEventListener(Event.COMPLETE, this.onComplete);
            urlStream.addEventListener(ProgressEvent.PROGRESS, this.onProgress);
        }
 
        public function download(url:String):void{
            // referencia o caminho do arquivo
            fileURL = url;
 
            // abre o filestream do arquivo
            urlStream.load(new URLRequest(fileURL));
 
        }
        private function onProgress(ev:ProgressEvent):void{
            // para uso de barra de progresso, porcentagem, etc.
            this.dispatchEvent(ev);
        }
 
        private function onComplete(ev:Event):void{
            // separa o nome do arquivo
            var urlParams:Array = fileURL.split("/");
            urlParams.reverse();
 
            // cria a referencia dos arquivos
            fileRef = File.applicationStorageDirectory.resolvePath(urlParams[0]);
 
            // abre o arquivo para escrita
            fileStream.open(fileRef, FileMode.WRITE);
 
            var byteArray:ByteArray = new ByteArray();
            urlStream.readBytes(byteArray, 0, urlStream.bytesAvailable);
 
            // escreve o arquivo temporario
            fileStream.writeBytes(byteArray, 0, byteArray.length);
 
            // fecha as streams
            urlStream.close();
            fileStream.close();
 
            // dispara o evento
            this.dispatchEvent(new Event(Event.COMPLETE));
        }
 
    }
}

Para usá-la, foi bem simples:

var fileDownloader:FileDownloader = new FileDownloader();
fileDownloader.addEventListener(Event.COMPLETE, this.downloadComplete);
fileDownloader.download('http://www.meusite.com/meuarquivo.jpg');
 
function downloadComplete(ev:Event):void{
    // download completo
}

Apenas justificando porque não usei URLLoader ao invéis de URLStream: porque apesar de não ter sido implementado, a classe URLLoader não me daria os bytes já carregados do meu arquivo para que (caso quisesse), fosse escrevendo o arquivo a medida que ele fosse baixado.

29set/090

Zend Framework – Extendendo classes

O Zend Framework é cheio de recursos (na maior parte das vezes, sobra), mas não quer dizer que estes sejam 100% ajustados a nossa necessidade. Quando nós olhamos pra fora (outros frameworks, linguagens), achamos coisas que gostaríamos que houvessem lá, mas, por enquanto, não existem. Solução: extendemos as classes!

Uma defesa clássica sobre extender classe é: nunca mexa no core! Claro! Você não vai sujeitar algo com 1 zilhão de commits e equipes desenvolvedoras as suas mãos falhas e exaltadas (nossa, que drama). A classe mais extendida, por ser a mais usada, é a classe do modelo: Zend_Db_Table. Quem já mexeu com Rails ou Cake sabe que faltam triggers de inserção ou validação, entre outras coisas.

Lá vem as pedras dizendo "já que tem que fazer, por que não migra logo pro outro?". Bom, vou ser rápido e responder que não vou discutir sobre isso.

Um exemplo de extensão e adição de triggers:

class Frk_Db_Table extends Zend_Db_Table {
 
    // dados da tabela
    protected $_data;
 
    /**
     * insere os dados validando os filtros
     * @param $data dados a serem inseridos na tabela
     * @return Integer Chave primaria da linha inserida
     */
    public function insert($data) {
        try {
            $this->_data = $data;
 
            // valida filtros de eventos anteriores
            if (method_exists($this,'before')) {
                $this->before();
            }
            if (method_exists($this,'beforeInsert')) {
                $this->beforeInsert();
            }
 
            // insere os dados e retorna a OK
            return parent::insert($this->_data);
 
        } catch (Exception $e){
            // trata o erro
            return FALSE;
	}
    }
}

Neste exemplo o método insert foi extendido para disparar dois triggers, befor e beforeinsert. Tomei esses dois exemplos vindo de outros frameworks. Muitas vezes são úteis. Segue um exemplo de implementação.

class Usuario extends Frk_Db_Table {
    protected $_name = 'usuarios';
 
    private function beforeInsert(){
        $this->_data['adicionado_em'] = date("Y-m-d");
    }
}

Sempre que for utilizado o método insert, a classe usuário adiciona o campo adicionado_em. É uma boa maneira de se economizar código, especialmente nas views, neste caso. Eu, particularmente, também sempre extendo a classe Zend_Controller_Action, com métodos que auxiliam durante os requests.

Categorias: PHP Sem Comentários
26set/090

Novo layout, nova idéia…

Além de ter achado esse tema legal pra mudar a cara do blog, daqui pra frente pretendo manter uma idéia diferente: já que eu não estou com tempo pra ficar produzindo coisa pra cá ainda, além dos planos daqui incluirem os screencasts (em breve), vou continuar postando o que eu achar de relevante com explicação por cima, pra não ficar com cara de "twittada".

Bom é isso aí.

26set/090

Zend_Date e MySQL Timestamp

Precisava colocar um campo daqueles clássicos "atualizado em", em Timestamp do MySQL, num projeto em ZF.

Voilá:

...
$now = new Zend_Date();
$info['update_at'] = $now->get(Zend_Date::W3C);
...
Categorias: PHP Sem Comentários
3ago/090

Silverlight on Mac OS

Silverlight on Mac OS

Silverlight on Mac OS


Será que é tão difícil reconhecer o meu OS? E melhor, que tal um link direto? Eu simplesmente ainda não consegui fazer o dowload do plugin, afinal, ele só libera o .EXE