Codificando, renderizando e fazendo download de uma imagem em base64 com javascript

Fala pessoal, esta semana tive de desenvolver uma funcionalidade bem bacana no projeto que estou atuando, como achei interessante gostaria de compartilhar este conhecimento.
Então vou ensinar vocês:
– Converter uma imagem para base64
– Renderizar a imagem na sua página
– Fazer o download

Mas o que é base64?

Base64 é um método para codificação de dados para transferência na Internet (codificação MIME para transferência de conteúdo). É utilizado frequentemente para transmitir dados binários por meios de transmissão que lidam apenas com texto. Por exemplo os envios de anexos por e-mail utilizam este método.

Convertendo arquivo de imagem em base64

Primeiramente vamos escrever o código html para fazer o upload do arquivo:

<div>
   <label>Selecione uma imagem</label>
</div>
<div>
   <input type="file" accept="image/*" (change)="processar($event)">
</div>

O método processar é responsável por interpretar o arquivo de imagem que fizemos upload, então é onde iremos aproveitar para converter nosso arquivo e recuperar as informações para podermos renderizar/fazer download do mesmo:

arquivoSelecionado: string; // guardará o src da imagem para renderizar
arquivoFormatado: string; // guardará o valor codificado em base64
arquivoNome: string;
arquivoExtensao: string;

processar(event) {
    // Recuperando a imagem, por padrão vem em uma lista
    const file = event.target.files[0];

    // Recuperando o nome do arquivo e extensão
    const arquivo: string = event.target.value;

    // Removendo o path C:\fakepath\ do nome da imagem
    this.arquivoNome = arquivo.split('.')[0].slice(0, 12);
    this.arquivoExtensao = arquivo.split('.')[1];

    // Objeto responsável por interpretar um arquivo
    const reader = new FileReader();

    // Este evento é chamado cada vez que a operação de leitura é completada com sucesso
    reader.onload = this._handleReaderLoaded.bind(this);

    // Inicia a leitura do conteúdo do Blob(objeto do tipo arquivo) especificado, uma vez finalizado, o atributo result conterá os dados raw binários do arquivo como string
    reader.readAsBinaryString(file);
  }

  _handleReaderLoaded(readerEvt) {
   // o método btoa codifica em base64
   const base64 = btoa(readerEvt.target.result);
   this.arquivoFormatado = base64;

   // src para renderizar a imagem
   this.arquivoSelecionado = "data:image/jpeg;base64," + base64;
  }

Exemplo de arquivo convertido em base64:

Renderizando a imagem

Agora que já temos nosso arquivo codificado em base64, conseguimos renderizar a imagem na nossa página, utilizando a variável arquivoSelecionado.

<div class="d-flex justify-content-center">
   <img [src]="arquivoSelecionado" alt="Selected Image"/>
</div>

Fazendo download do arquivo

Primeiro vamos criar o HTML do botão:

<button type="button" class="btn m-btn--air btn-outline-primary btn-sm mr-2" (click)="download()">
   <span>Download</span>
</button>

Agora vamos para o código responsável pelo download:

download() {
    // o metodo atob decodifica base64
    const binaryString = atob(this.arquivoFormatado);
    const bytes = new Uint8Array(binaryString.length);
    // convertendo em array buffer do tipo Uint8Array
    const arrayBuffer = bytes.map((byte, i) => binaryString.charCodeAt(i));

    this.criarArquivoParaDownload(arrayBuffer);
  }

  criarArquivoParaDownload(body) {
    // A partir do array buffer criamos o arquivo para download
    const blob = new Blob([body]);
    const fileName = `${this.arquivoNome}.${this.arquivoExtensao}`;

    // Validação para navegadores
    if (navigator.msSaveBlob) {
      // IE 10+
      navigator.msSaveBlob(blob, fileName);
    } else {
      const link = document.createElement('a');
      // Navegadores que suporta atributo de download do HTML5
      if (link.download !== undefined) {
        // criando um atributo hidden, para simular o click e disparar o download
        const url = URL.createObjectURL(blob);
        link.setAttribute('href', url);
        link.setAttribute('download', fileName);
        link.style.visibility = 'hidden';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      }
    }

Clicando agora no botão de Download, o arquivo será baixado pelo seu navegador!
Com isso terminamos o nosso post de hoje!
Espero que este material sirva de apoio para vocês algum dia 🙂

Entendendo um pouco do conceito de REST e protocolo HTTP

Sabe-se que atualmente (2019) boa parte das aplicações, empresas e serviços se comunicam através de APIs, que não nada mais são que serviços expostos na internet para consumo de terceiros. Permitindo facilmente que o mesmo serviço possa ser consumido por um aplicativo móvel, um site de internet ou um aplicativo em seu desktop, desde que tenha acesso à internet.

Futuramente iremos debater sobre outros meios de comunicação e integração como SOAP e GraphQL, mas vamos do princípio mais básico.

O que é REST?

REST é um acrônimo para REpresentational State Transfer, ou seja, Transferência de Representação de Estado. Que nada mais é do que troca de informações utilizando o protocolo HTTP.

Um pouco de HTTP

As requisições feitas por uma RESTful API são através do protocolo HTTP onde temos:
– Endpoint: endereço do serviço
– Verbo HTTP: ação a ser tomada a partir do endpoint
– Payload: corpo da requisição podendo ser JSON ou XML

Dentre os verbos / métodos possíveis: Referência

  • GETO método GET solicita a representação de um recurso específico. Requisições utilizando o método GET devem retornar apenas dados.
  • HEAD O método HEAD solicita uma resposta de forma idêntica ao método GET, porém sem conter o corpo da resposta.
  • POST O método POST é utilizado para submeter uma entidade a um recurso específico, frequentemente causando uma mudança no estado do recurso ou efeitos colaterais no servidor.
  • PUT O método PUT substitui todas as atuais representações do recurso de destino pela carga de dados da requisição.
  • DELETEO método DELETE remove um recurso específico.
  • CONNECT O método CONNECT estabelece um túnel para o servidor identificado pelo recurso de destino.
  • OPTIONSO método OPTIONS é usado para descrever as opções de comunicação com o recurso de destino.
  • TRACE O método TRACE executa um teste de chamada loop-back junto com o caminho para o recurso de destino.
  • PATCHO método PATCH é utilizado para aplicar modificações parciais em um recurso.

HTTP Status, toda requisição HTTP retorna seu código de status nos avisando se a requisição foi processada com sucesso, se teve retorno, se deu algum tipo de erro e etc. Estes códigos apesar de programáveis (seu backend pode definir que tipo de HTTP Code retornar), são ótimos indícios de como sua API se comporta.

Exemplo:
> 1xx Informativo
> 2xx Sucesso
> 3xx Redirecionamento
> 4xx Erro lado do cliente
> 5xx Erro lado do servidor

Referência completa: Link

JSON x XML

É possível utilizar tanto XML quando JSON para requisições ou respostas em serviços REST. Porém comumente o uso de JSON por ser muito mais leve e de fácil entendimento, leitura e menos verboso que XML. Mas não há uma regra e sim varia conforme a necessidade de sua aplicação ou cliente.

//JSON de Cliente
{
  name: 'John',
  age: 33,
  gender: 'M'
  children: [
    {
      name: 'Mike',
      age: 5,
      gender: 'M'
    }
  ]
};
//XML de Cliente (Forma Representativa)
<client>
  <name>John</name>
  <age>33</age>
  <gender>M</gender>
  <children>
    <child>
      <name>Mike</name>
      <age>5</age>
      <gender>M</gender>
    </child>
  </children>
</client>

REST x RESTful

De uma forma bem resumida, podemos dizer que REST é o conceito arquitetural e RESTful é forma de aplicar este conceito de forma prática.

RESTful API

Uma vez definido nosso endpoint lá no backend, utilizaremos (tese) este mesmo endpoint para operações diferentes dentro da nossa aplicação e a melhor forma de exemplificar é utilizando serviço de CRUD.

http://{my-app.com}/api/{domain}

Seguindo o exemplo acima digamos que seu domínio seja de Cliente e partir dai queremos executar determinada operação através dos verbos disponíveis, olha que prático:

GET: http://{my-app.com}/api/client //listar todos
GET: http://{my-app.com}/api/client/{id} // recuperar por id
DELETE: http://{my-app.com}/api/client/{id} // remove client por id
PUT: http://{my-app.com}/api/client //atualizar, porém é necessário body com os dados cliente
POST: http://{my-app.com}/api/client //salvar, porém é necessário body com os dados cliente

Exemplo de payload em JSON:

const client: Client = {
  name: 'John',
  age: 33,
  role: 'user',
  gender: 'M'
};

Resumo

Espero ter ajudado em dar um overview sobre conceitos básicos e práticos de REST, HTTP com REST, RESTful, JSON. Em um futuro próximo faremos alguns tutorias para consolidar o conceito com a prática real. Mas antes de fazer tutoriais é necessário saber o porque está usando aquela abordagem, se realmente se aplica ao cenário que está enfrentando e por ai. Até a próxima!

O que é Node.js?

Fala pessoal, hoje iremos falar um pouco sobre Node.js, já ouviram falar?
Acredito que sim! Pois a tecnologia vem dominando cada dia mais o mercado. Então vamos lá!

O que é Node.js?
Resumidamente falando, é uma plataforma utilizada para construir aplicações web escaláveis de alta performance com JavaScript.
A tecnologia foi construída com base no interpretador V8 JavaScript Engine feita nada mais, nada menos do que pela Google. A sua arquitetura é orientada a eventos ou seja, uma rotina fica monitorando até que o evento programado seja acionado assim retornando uma resposta.

Mas qual a vantagem de utilizar o Node.js?
O Node.js trabalha de forma assíncrona e sem bloqueios, o que significa que não é necessário esperar uma requisição terminar para iniciar outra. Isso é uma arma muito poderosa, pois consegue lidar com um grande volume de requisições e garante rapidez nas respostas .
A sua leveza também é um destaque, pois não é necessário grandes recursos de utilização do computador .

Node.js X NPM
NPM ( Node Package Manager ) é um repositório online para publicação de código aberto para o Node.js, e também através dele é possível instalar os pacotes contidos neste repositório.
Então por possuir um grande repositório que fornece pacotes de códigos reusáveis gratuitamente via NPM é uma outra grande vantagem do Node.js, ou seja, caso precise fazer integrações com outros sistemas e/ou banco de dados é possível que já exista a solução implementada.

Tudo isso é muito bom, mas e as desvantagens?
Por trabalhar de forma assíncrona, é preciso tomar cuidado com o famoso callback hell, que significa ter várias camadas de retorno, uma dependendo da outra, assim deixando muito complexo o entendimento para outros programadores e para manutenções de código.
Não é recomendado a utilização do Node.js, para sistemas que tem lógicas muito complexas e necessitam de uma utilização maior da CPU.

Espero que algumas dúvidas em relação a tecnologia tenha sido esclarecida!
Em breve faremos alguns tutoriais desde a instalação até a utilização da tecnologia 😉

Para mais informações: https://nodejs.org/en/



Onde devo buscar material de apoio?

Por impulso natural temos a tendência de jogar no Google nossas dúvidas de forma desordenada, seja um erro qualquer, uma palavra chave, um trecho código, uma instrução SQL ou algo do gênero. E não estamos errados em fazer isso, pois sempre antes de pedir um apoio de alguém mais experiente (trabalho) é interessante limitar suas alternativas. Mas e quando estamos em casa, ou na faculdade, ou na casa de um amigo, para onde devemos correr quando se vemos sem um ponto de apoio?

Costumo dizer que antes de sair por ai disparando tiros para todos os lados esperando alguém te socorrer, precisa antes de tudo mesmo se situar. O que seria isso? Bom, vamos por partes:

Qual o meu problema? (Neste ponto precisa entender o que é o seu problema, como chegou nele, os passos que seguiu para chegar até onde chegou)

Qual deveria ser o resultado esperado? (Aqui precisa ter bem claro o que você pretendia antes de começar o passo acima, pois muitas das vezes revendo o caminho que trilho, sozinho percebe onde errou ou no meu caso uma forma até mais simples de executar aquela tarefa)

Como explicar isso para uma pessoa de fora / externa ao meu problema de uma forma clara e que ela entenda? (Este é o mais difícil, nem o mais experiente dos arquitetos consegue fazer isso sempre, mas não nos impede de tentar, nem que tenhamos que fazer mimica ou desenhar)

Com isso em mãos, podemos facilmente ir no Google, Foruns sobre o assunto, perguntar aos colegas de trabalho, cursos sobre o assunto em questão uma vez que já entende o problema, tendo uma abstração maior do conceito na qual o engloba, cursos práticos e rápidos tendem à ajudar.

Espero ter dado uma luz, mas se veio em busca de referências, seguem algumas:

GUJ

Stackoverflow

Ultimate Courses

John Papa