domingo, 11 de julho de 2010

Tratamento de erros no upload

Olá pessoal,

esse mês eu estava trabalhando na construção de um módulo que fará uploads de arquivos para o site http://br.especiais.yahoo.com/fanzone/. O módulo estava funcionando muito bem, até que o time de QA encontrou um bug muito interessante!
No nosso caso, nossos servidores estavam configurados para aceitar arquivos de até 150MB. Pois a tester resolveu enviar um arquivo de 200MB para ver no que dava. Dito e feito, o módulo simplesmente falhou e retornava em branco. Perceba que o módulo não enviava nenhum tipo de mensagem de erro, estou falando daquelas mensagens que o usuário até assusta quando vê!
Como a nossa idéia era tratar o erro de forma amigável, a nossa equipe foi atrás de uma solução para mostrar ao usuário que o arquivo que estava sendo enviado, era muito maior que o que o servidor suportava.
Para aqueles que tem um browser com javascript, foi fácil. Como estamos utilizando o YUI Uploader, apenas conferimos a propriedade size provida pelo método fileSelect. Claro que o back-end passou o valor suportado pelo server para o JS. Mas o que fazer se o usuário tem um browser com JS desabilitado ou que não suporta JS?

Nesse caso, reduzimos o tamanho permitido para upload, pois poderíamos testar mais facilmente:
[php.ini]
post_max_size = 2M
upload_max_filesize = 2M
(depois de alterar o php.ini, não se esqueça de reiniciar o apache)

Ao tentar enviar um arquivo maior que 2MB, recebemos a seguinte mensagem de erro:

PHP Warning: POST Content-Length of 2202010 bytes exceeds the limit of 2097152 bytes in Unknown on line 0

Depois de pensar um pouco, chegamos à seguinte solução com o PHP:

// If we have a POST request with _POST and _FILES array empty,
//we have either an error in the request or a file that is bigger than the server can handle
if($_SERVER['REQUEST_METHOD'] == 'POST' && empty($_POST) && empty($_FILES)){
  //get the size that the server can handle
  $max = ini_get('post_max_size');

  //check if the content_length is bigger than the size the server can handle
  if($_SERVER['CONTENT_LENGTH'] > $max){
    return $this->returnError('The file you are trying to upload is bigger than the allowed');
  }else{
    return $this->returnError("There's an issue with the request");
  }
}

Perceba que testamos se o $_POST e $_FILES estão vazios. É isso que estava ocorrendo quando o usuário enviava um arquivo muito grande. Como o arquivo PHP em questão sempre deveria receber um arquivo via método POST, pudemos fazer esse teste. Se no seu caso, o formulário pode ser enviado com um arquivo sendo opcional, então essa solução pode não ser boa pra você.

Bom... sei que à primeira vista parece ser um problema simples que nem merece a nossa atenção, mas se você quer realmente prover uma boa experiência aos usuários, é bom capturar essa situação e devolver uma mensagem adequada.

Abraços e até o próximo post! (quando será?!?)

quinta-feira, 22 de outubro de 2009

Site checklist - 10 itens importantes

Nossa, quase dois anos depois eu volto a postar alguma coisa!
O importante é não parar :)

Onde estou trabalhando (Ci&T, projeto Yahoo!), tenho me preocupado muito com a performance dos sites lançados, uma vez que serão divulgados nas frontpage do Yahoo! pelo mundo, portanto, reuni uma lista de 10 itens importantes para o lançamento de um site que se preze.

A idéia aqui é mais levantar os itens interessantes do que mostrar o como fazer. Talvez esse seja uma assunto para outros posts. Também devido ao meu background de Engenheiro de Software, posso deixar escapar algum importante item que um Engenheiro de Interfaces poderia levantar. Qualquer coisa, deixa um comentário.
Certamente há itens para serem descritos, mas pra não ficar chato, vamos com dez itens mesmo.

A lista estará numerada, mas isso não significa que devemos executar os itens nessa ordem.

Vamos à lista:

1) Tratamento de erros: Página 404 com links para páginas existentes
Um site que não possui essa característica poderá perder potenciais visitantes que por um motivo ou outro seguiu um link antigo e que não existe mais no site.
Seria muito bom uma página 404 inteligente que analisa a página incorreta e tenta oferecer links relevantes. Pode-se, por exemplo, 'estudar' quais as páginas 404 que mais tentam ser acessadas e algum editor informar quais os links devem ser mostrados.
Esse mesmo princípio pode ser aplicado à erros 403 (Forbidden) também.

2) Markup válido: Páginas são documentos [X]HMTL válidos
Páginas que não são documentos válidos tem maior tendencia de não serem renderizadas consistentemente nos diferentes browsers e, provavelmente, será uma grande bagunça quando navegando de um dispositivo móvel.

3) Acessibilidade mínima: todos tem o direito de ver o seu site
Vamos ver em sub-tópicos para melhor organização:
a) O site deve ser renderizável em IE 7, IE 8, FF 3, Safari e Chrome (Opera?).
b) Não se esqueça de testar no Windows, OSX e Linux, pois podem apresentar diferenças quando seus browsers renderizam as páginas.
c) O site deve ser utilizável em diferentes resoluções de tela.
d) Se a fonte for alterada (principalmente aumentando...), o site ainda deve ser utilizável.
e) E se o CSS for desabilitado? O site ainda é legível?
f) E se o Javascript for desabilitado? Ainda é possível utilizar o site?
Caso você deixe de implementar um dos itens acima, uma porcentagem de seus usuários podem experimentar uma fraca experiência ao acessar o seu site.

4) Web semântica: uma www mais organizada
Para que seu site fique acima da média, procure ter uma descrição relevante e precisa no title, meta-description e meta-keywords:

<title>Checklist para lançamento de sites de grande volume de acesso</title>
<meta name="description" content="Pouco tempo após o lançamento de um site, seus criadores descobrem que alguns pontos essenciais foram esquecidos, isso pode ser facilmente evitado com a adoção de um checklist.">
<meta name="keywords" content="minify, gzip, semantica, acessibilidade, favicon, cache, checklist">


Sem essas 'simples' três tags, seu rank nos sistemas de busca será penalizado e muito. Um título relevante também melhora a experiência de uma usuário que incluirá a página em seu favoritos ou busque no histório sobre aquele site interessante que ele viu anteriormente.

5) Arquivo para crawlers: robos são seres insistentes
É imprescindível para um site ser encontrado pelos mecanismos de busca. Para tanto, se faz necessário incluir um simples arquivo texto, chamado robots.txt, na raiz do site. Mesmo que seja o caso para orientá-lo a indexar todas as páginas do site:

User-Agent: *
Disallow:

Se o arquivo robots.txt não existir no site, seu error log será entupido com mensagens de erro 404 do tipo 'robots.txt file not found', geradas por todos os crawlers de busca que tentarem acessar o arquivo não existente. Portanto, crie um simple arquivo robots.txt e seu servidor já será livrado de mais uma 'dor de cabeça'

6) Favicon: quem inventou isso hein?!?
Favicon, diminuto de Favorites Icon, são aqueles pequenos ícones que poder ser visto à esquerda da barra de navegação. Seu valor é questionável, pois a maioria das pessoas nem presta atenção nele.
Mas se você omitir o favicon, praticamente todo o visitante de seu site adicionará uma linha com '404 favicon.ico not found' no log do servidor.
O efeito, é o mesmo do robots.txt descrito no item 5, porém muitas vezes ampliado, afinal, robots.txt apenas crawlers procurar mas favicon, praticamente todos os browsers o querem!

7) JS e CSS em arquivos separados: porque HTML, é HTML (!!!)
Não misture JS e CSS com HTML. Mova todo o código JS e CSS embutido no documento HTML para um arquivo separado, pois assim, o browser poderá fazer cache do conteúdo e quando for solicitar a página HTML, não precisará de fazer o download de todo o código JS e CSS novamente.
Claro que pra toda regra há uma exceção. Nesse caso, se o seu código JS e/ou CSS for utilizado apenas em uma das páginas do site, não tem porque separar em um arquivo.
Ao executar esse passo, você se beneficiará do passo seguinte:

8) CSS e JS minificados: computadores não precisam de identação ou comentários
Os arquivos CSS e JS devem ser reduzidos ao máximo que for permitido.
Minificar é o ato de retirar todos os espaços em branco (espaço, quebra de linha e tab), comentários além de implementar outras técnicas como:

- consolidação de CSS e JS:
Todos os arquivos CSS serão agrupados em apenas um arquivo, bem como os arquivos JS.

- refactoring do JS
Variáveis serão renomeadas para ficarem menores. Por exemplo: showUserDetails e isModernBrowser se tornariam v1 e v2 respetivamente.

Com os arquivos minificados e consolidados em apenas um arquivo JS e apenas um arquivo CSS, a quantidade de bytes sendo transferida reduz drasticamente e com apenas dois arquivos JS e CSS, poucas requisições HTTP terão de ser abertas para solicitar os arquivos.

9) Sprite de imagens: não, não é de beber
Uma coisa que as vezes passa desapercebido, é a quantidade de requisições HTTP quem site tem que fazer para carregar as 55 imagens que compões o site.
Essas requisições tomam um tempo considerável do browser para receber todas as imagens.
Para evitar esse problema, coloque todas as imagens em uma só e utilize CSS para posicioná-las.

10) Cache no servidor: de volta às páginas estáticas
Muitas vezes nos gabamos de ter um site dinamico, mas a página principal (a que recebe todos os visitantes), não é atualizada muitas vezes num dia.
As vezes, uma ou duas vezes por dia. Com isso em mente, pra que abrirmos conexão no banco para pegar sempre a mesma informação, processá-la e aprensentar 1.000 vezes num dia?
Nesse caso, recomenda-se cachear pelo menos a index page, para que apenas quando for necessário, montaremos a página e a salvaremos de modo estático no servidor. Dessa maneira, o servidor web não ficará 'bloqueado' aguardo o processamento da página entregar o conteúdo.

Se o seu projeto cobrir esses itens, posso dizer que ele está a frente de muitos outros!


Fica assim então... a data do próximo post a DEUS pertence! :P

quinta-feira, 20 de dezembro de 2007

URLs Amigáveis com Apache e PHP

Nesse artigo veremos como implementar URL’s mais amigáveis para as pessoas acessarem nosso site, sem o “trauma” de ver “códigos esquisitos” na barra de endereço do browser.

Outra motivação de implementarmos as URL’s amigáveis em nossos sites, é para sermos rastreáveis por spiders que normalmente ignoram arquivos com extensão que denotam programas que retornam conteúdo variável.

Essa técnica que passaremos aqui ajuda a destacar nosso site em sites de busca como o Google ou Yahoo e é uma ferramenta da SEO (Search Engine Optimization).

Se você não está entendendo direito o que estou dizendo vamos para um exemplo. Imagine que tenhamos um site que mostra artigos e informações sobre seus autores. Sem a utilização das URL’s amigáveis, poderíamos acessar um artigo da seguinte maneira:

http://www.sitedeartigos.com.br/artigo.php?id=123

Agora, utilizando a técnica que será passada por esse artigo, poderíamos acessar nosso site da seguinte maneira:

http://www.sitedeartigos.com.br/artigo/123

A URL acima é muito mais interessante de se ler do que a primeira URL informada. Creio que com esse simples exemplo, podemos entender qual o benefício que obteremos após aprendermos essa técnica.


Configuração do Apache
Como tudo na nossa área de programação, há várias
maneiras de se atingir um mesmo objetivo. Utilizarei uma técnica que desviará
qualquer chamada para o arquivo index.php que será o nosso manipulador de
requisições. Portanto, tudo passará pelo index.php e ele será o responsável por
carregar os arquivos corretamente.

A versão do Apache que estou utilizando é a 2.2.4.


1) Vá até o arquivo httpd.conf e descomente a linha
# LoadModule rewrite_module modules/mod_rewrite.so
Para descomentar, basta retirar o símbolo de cerquilha na frente da linha.
Essa alteração nos permitirá manipular as requisições, redirecionando-as para o arquivo index.php

2) Ainda no arquivo httpd.conf, localize a linha onde há a diretiva <Directory /> e garanta que tenha a seguinte linha dentro da diretiva: AllowOverride All.
Essa alteração nos permitirá utilizar o arquivo
.htaccess.

3)Reinicie o serviço do Apache


Configuração do arquivo .htaccess
Para nosso exemplo, vamos assumir que o site será testado dentro do diretório thiagomp que por sua vez tem o diretório teste.
Dentro do diretório teste ficará nossos arquivos PHP, inclusive o arquivo
index.php.
Portanto, nossa URL base seria http://localhost/thiagomp/teste.
Para funcionar o esquema, crie um arquivo chamado .htaccess (repare que há um ponto antes do nome do arquivo...) com o seguinte conteúdo:

RewriteEngine on
RewriteRule .* index.php
php_flag magic_quotes_gpc off
php_flag register_globals off

Repare que ligamos o motor de reescrita com a primeira linha e depois implementamos a regra de redirecionamento. A regra é bem simples: qualquer coisa que for informada, deve ser redirecionada para o arquivo index.php.

As outras duas opções nem seriam tão necessárias, mas são ótimas para garantir segurança e a sanidade de nossos códigos.

O arquivo .htaccess deve ser salvo dentro do diretório teste.


Arquivos para o teste
Abaixo será mostrado os arquivos utilizados para o testes com comentários. Tais arquivos foram testados com o PHP versão 5.2.4.

artigo.php

<?php
$idArtigo = isset($parameter['id']) ? $parameter['id'] : 0;
if(empty($idArtigo)){
  echo "<h2>Não foi selecionado o ID do artigo</h2>";
}else{
  echo "<h2>Mostra o artigo de ID $idArtigo</h2>";
}

autor.php
<?php
$idAutor = isset($parameter['id']) ? $parameter['id'] : 0;
if(empty($idAutor)){
  echo "<h2>Não foi selecionado o ID do autor</h2>";
}else{
  echo "<h2>Mostra informações do autor de ID $idAutor</h2>";
}


naoencontrada.php
<?php
echo "<h2>Página não encontrada</h2>";

index.php
<?php
/**
 * Recupera a URL solicitada e quebra cada parte dela.
 * Portanto, se a URL for algo do tipo http://localhost/thiagomp/teste/artigo/10 obteremos o seguinte array:
 * array(5) {
 *  [0]=>  string(0) ""
 *  [1]=>  string(6) "thiagomp"
 *  [2]=>  string(12) "teste"
 *  [3]=>  string(6) "artigo"
 *  [4]=>  string(1) "10"
 * }
 *
 * Com isso poderíamos convencionar que em nosso site, tudo o que vier depois da URL base, primeiro virá o nome do arquivo que vamos invocar e depois os parametros, sendo que primeiro parametro será sempre um ID
 */


$parts explode('/'$_SERVER['REQUEST_URI']);

/**
 * Esse trecho testa quantos diretórios há na URL solicitada. Dependendo da quantidade de diretórios passados, nosso programa ajustará os valores que serão procurados nas páginas invocadas
 */
if(count($parts) == 5){ // o usuário informou uma pagina e um ID
  $params array_slice($parts, -2);
  $pagina $params[0];
  $id $params[1];
}elseif(count($parts) == 4){ //o usuário informou apenas a pagina
  $params array_slice($parts, -1);
  $pagina $params[0];
  $id 0;
}else{ // nada foi informado
  $pagina "nenhuma";
  $id 0;
}

switch ($pagina){ //seleciona a página
  
case 'artigo'// implementamos o que queremos fazer quando uma determinada página for encontrada...
    $parameter[
'id'] = $id// configura o parametro que será recuperado na $pagina.php
    include("$pagina.php"); //... nesse caso vamos incluir o arquivo para execução
    break;
  case 'autor'
//idem ao artigo
    
$parameter[
'id'] = $id;
    include("$pagina.php");
    break;
  default: 
//caso a página solicitada não exista, mostraremos um erro
    
include('naoencontrada.php');
}


Depois de copiar os conteúdos e gravá-los em
arquivos, basta efetuarmos um teste colocando no browser a URL http://localhost/thiagomp/teste/artigo/10

Espero que esse artigo seja útil para lhe dar uma
noção sobre o funcionamento das URL’s amigáveis. Com certeza é um exemplo muito
simples, porém, para quem está iniciando, será muito bom para compreender o
conceito e continuar o desenvolvimento dos conhecimentos nessa área.

Caso algum erro ocorra com os arquivos ou tenha algo
para acrescentar, fique a vontade de comentar.

Até o próximo post.

domingo, 21 de outubro de 2007

Tempestade de poeira

Hoje o post não é nada sobre Tecnologia.
É para mostrar uma tempestade de poeira que chegou aqui em Ribeirão Preto.

Vejam as fotos e o vídeo abaixo:







Abraços e até o próximo post.

terça-feira, 25 de setembro de 2007

Problema de acentuação com PHP e JSON

Hoje estava trabalhando em uma aplicação com AJAX e me deparei um com problema de acentuação no retorno de alguns dados via JSON do MySQL.
Se em algum campo tiver a palavra "Éramos", por exemplo, ao executar um encode (utilizei a Services_JSON provida pelo PEAR), ele retornará algo como \u0072amos que será renderizado como "ramos".
Depois de googlar sobre o assunto, descobri uma maneira de evitar esse problema.
Considere que o código abaixo é um PHP que retorna dados no formato JSON

<?php
header('Content-type: application/json charset=iso-8859-1');

/*
* codigo para conexao no banco e enviar consulta
* ...
*/

while($row = fetch()){
array_walk($row, 'toUtf8');
$data[] = $row;
}

/*
* codigo para terminar de montar o array de retorno dos dados
*/

require_once('JSON.php');
$json = new Services_JSON();
echo
$json->encode($returnValue); // Instead of json_encode


function toUtf8(&$item, $key) {
$item = iconv("iso-8859-1","utf-8",$item);
}

O segredo está aqui:
$item = iconv("iso-8859-1","utf-8",$item);

O fato de converter todas strings para utf-8 utilizando a iconv, garantiu que meus dados fossem renderizados corretamente.

Por hoje é isso!
Abraços.

quarta-feira, 5 de setembro de 2007

Desenvolvimento para Linux

Após longos seis meses volto a postar no blog!
Não vou prometer nada, mas espero blogar mais.
Fui questionado sobre quais as ferramentas para desenvolvimento de software desktop para Linux. Quem fez pergunta era um programador Delphi.


Para quem trabalha com Delphi, existe o compilador freepascal e GNU Pascal Compiler.
Também tem o Lazarus que é uma IDE inspirada no Delphi.
Quem trabalha com Delphi normalmente utiliza o Firebird. O Firebird também pode
ser instalado no Linux.
Também tem o MySQL que é um banco de dados muito difundido e o PostgreSQL que é um banco menos difundido, porém poderoso.

Agora, se você está realmente querendo mudar, Java é a melhor opção de desenvolvimento para Linux, na minha opinião.
Tem um ótimo IDE free, o NetBeans, que se conecta em praticamente todos os databases, graças a arquitetura do JDBC de Java.

Outra ferramenta que vem ganhando bastante espaço em desenvolvimento desktop para Linux é o PHP-GTK. O PHP
é uma linguagem já muito utilizada para desenvolvimento web e com extensa gama de APIs para conexão nativa aos bancos de dados mais utilizados no mundo. Com essa extensão, ficou fácil o programador que já conhece PHP também desenvolver para desktop.

Não poderia deixar de citar o projeto MONO. Não o conheço muito, mas pelo que tenho lido, é uma ótima opção de desenvolvimento utilizando uma plataforma parecida com o .NET da Microsoft. O Sharp Develop é uma ótima IDE gratuita.
Seguindo essa linha, há o Real Basic, HBasic e Gambas, para programadores Visual Basic.
Certamente há mais opções como Python, QT, C, C++, Jython, Tcl/Tk , JRuby, entre outras.


Abraços e até o próximo post

quinta-feira, 1 de março de 2007

Delphi for PHP


Mais uma IDE para desenvolvimento disponível no mercado: Delphi for PHP.
A CodeGear, empresa criada pela Borland para dar continuidade aos produtos para desenvolvedores, adaptou o seu produto para o desenvolvimento de PHP. Eles já aceitam pedidos, mas entregarão o produto em março (não foi especificado o dia específico).
Não encontrei nada do site informando se haverá alguma versão para avaliação do produto, mas já enviei um email para eles perguntando sobre isso.

Fiquei muito feliz de saber dessa notícia, pois é uma empresa que desenvolve um produto amplamente conhecido como o Delphi (entre outros...) e demonstra a força que PHP tem exercido no mundo dos desenvolvedores.
A IDE foi devidamente adicionada a lista de editores de PHP que mantenho aqui no blog.

A ferramenta tem um preço sugerido de US$ 249,00.
Para os mais curiosos, existe um vídeo para ver a ferramenta em ação.

Abaixo mais um screeshot publicado no site da CodeGear.



Mais informações:
Notícia do lançamento do produto pela CodeGear (em inglês)
Info online (em português)

Abraços e até o próximo post.