Normalmente, quando fazemos o upload de uma imagem nós precisamos redimensiona-lá para reduzir seu tamanho. Esse processo normalmente é feito do lado servidor, ou seja, enviamos a imagem na sua forma e tamanho original e então redimensionamos no servidor utilizando PHP, por exemplo.

Porém, em um aplicativo de galeria de fotos, por exemplo, o usuário normalmente baixa as fotos (em alta resolução) de sua câmera e quer em seguida enviar para o aplicativo. Supondo que ele deseja enviar 200 fotos, cada uma com 5 MB, seria necessário fazer o upload de 1 GB de dados para o servidor, para que então possamos reduzi-las em um tamanho viável.

Sendo assim, pretendo apresentar nesse artigo uma solução para este problema. Vamos ver como redimensionar a imagem antes de enviar ao servidor, utilizando Javascript. Para isso faremos um formulário para envio de várias imagens que serão salvas em uma pasta no servidor.

Confira o exemplo em funcionamento, clicando aqui.

O formulário

Criamos um formulário com um input para envio das imagens. Utilizamos a propriedade accept para definir que só serão permitidos imagens e a propriedade multiple que permite o envio de várias imagens. Criamos também uma barra de progresso que será utilizada para indicar o progresso de envio, utilizando Bootstrap. Além do JQuery e Bootstrap, utilizaremos também a biblioteca resize.js que facilitará o redimensionamento.

O lado cliente

Primeiramente, vamos declarar as variáveis que serão utilizadas e definir os eventos.

Iniciamos a biblioteca, criamos a variável imagens que será utilizada para armazenar as imagens e a variável imagem_atual que será utilizada para controlar o índice da imagem que está sendo enviada. Vinculamos um evento change no nosso input, ou seja, quando o usuário selecionar os arquivo esse evento será chamado, que por sua vez, chamará a função enviar().

Enviar

Vamos criar a função para iniciar o envio da imagens.

Primeiramente, verificamos se o navegador do usuário possui os recursos necessários para manipulação de arquivos. Alocamos as imagens selecionadas na variável imagens. Verificamos se alguma imagem foi selecionada; caso haja, iniciamos a barra de progresso, escondemos o input, zeramos a variável de controle e chamamos a função redimensionar().

Redimensionar

Essa função é responsável por redimensionar, salvar e passar para próxima imagem recursivamente. Isso é necessário pois o processo de redimensionamento da imagem é assíncrono, ou seja, o resultado não é retornado imediatamente, portanto não podemos fazer um simples for percorrendo as imagens e redimensionando. Sendo assim, a variável global imagem_atual é quem controla o fluxo das imagens.

  • Linha 7 até 20: Essa função será chamada recursivamente, ou seja, por ela mesmo. Portanto precisamos ter um ponto final, que no caso é quando nossa variável de controle imagem_atual for maior que a quantidade de imagens. Caso isso aconteça, exibimos uma mensagem de sucesso e finalizamos a chamada da função;
  • Linha 23 até 29: Este teste é necessário, pois alguns navegadores incluem um valor nulo quando armazenamos a imagem do input, portanto caso não seja uma imagem válida, passamos para a próxima imagem, ou seja, incrementamos a variável de controle, chamamos a função novamente e finalizamos essa chamada;
  • Linha 32: Chamamos o método de redimensionamento da biblioteca. Passamos como parâmetro a imagem (imagens[imagem_atual]), a largura em pixel para qual a imagem será redimensionada, o tipo do retorno (dataURL ou file) e por fim o callback, ou seja, a função que será chamada quando o processo finalizar;
  • Linha 35: Neste trecho a imagem já foi redimensionada e está armazenada na variável imagem, portanto fazemos uma requisição AJAX ao servidor, passando a imagem via método POST;
  • Linha 38: Através de um cálculo simples, definimos a porcentagem que a imagem atual representa no total de imagens;
  • Linha 41: Definimos a porcentagem atual da barra de progresso;
  • Linha 46 até 50: Através da função setTimeout(), definimos que o trecho de código adiante só será chamado após um segundo. Isso é interessante para evitar sobrecarga no servidor e até mesmo no navegador do usuário, e também para a barra de progresso ficar mais suave. Sendo assim, um segundo após a imagem ser salva no servidor, passamos para a próxima imagem.

Limpar

Utilizamos este método para limpar o input. É necessário para funcionar em versões anteriores do Internet Explorer.

O lado servidor

Recebemos a imagem no servidor em formato base64. Precisamos converte-lá em arquivo para salvá-la em disco.

Recebemos e armazenamos a imagem. Através das funções list() e explode() do PHP, separamos as informações contidas na imagem. Convertemos a imagem para arquivo através da função base64_decode(), geramos um nome único para ela e salvamos em uma pasta do servidor utilizando a função file_put_contents().

Conclusão

O redimensionamento de imagens no lado cliente reduz drasticamente o tempo de espera no envio das imagens, porém requer mais processamento da máquina do usuário, pois o redimensionamento está sendo feito pelo próprio navegador, mesmo assim é muito vantajoso quando trabalhamos com grande quantidade de imagens.

Vimos um exemplo simples que utiliza uma biblioteca pronta para fazer o redimensionamento, caso você precise de algo mais complexo será necessário entender melhor sobre a Canvas API do HTML5, que possibilita manipular diversos aspectos da imagem.

Enfim, espero que este exemplo tenha sido útil para você entender como funciona o redimensionamento de imagens no lado cliente.

Código fonte disponível em: https://github.com/rafaelcouto/Post1334

Referências