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á?!?)

4 comentários:

Caio Penna disse...

Ótimo post, essa experiência demonstra uma preocupação importante, que infelizmente nem todos os profissionais têm.
Ainda somos poucos que temos o objetivo de proporcionar uma boa experiência ao o usuário.

Anônimo disse...

thanks for this tips

Souzace disse...

Obrigado!

Anônimo disse...

Ótimo compartilhamento!
Parabéns pela iniciativa.