DEV Community

Wesley Oliveira
Wesley Oliveira

Posted on

3 1 1

Flutter Image File Upload - Base64 x MultiPart Form

Recentemente comecei a pesquisar diferentes temas que poderiam ser utilizados para escrever algum conteúdo, foi aí que um amigo escreveu o primeiro artigo e utilizou de um problema que aconteceu em seu dia a dia para transformá-lo em uma ideia de artigo, para escrever esse pequeno artigo resolvi tentar da mesma maneira.

Passamos por uns erros no quesito de upload de uma imagem para a api via Base64, resolvi então mostrar aqui alguns problemas dessa abordagem e uma alternativa para a mesma.

Base64 é um método para codificação de dados para transferência na Internet. É utilizado frequentemente para transmitir dados binários por meios de transmissão que lidam apenas com texto, como por exemplo para enviar arquivos anexos por e-mail.

Para converter um arquivo para Base64 no flutter é muito simples vide código baixo:

File file = await ImagePicker.pickImage(source: ImageSource.camera);
String base64 = base64Encode(file.readAsBytesSync());
Enter fullscreen mode Exit fullscreen mode

¹ ImagePicker - Plugin Flutter para iOS e Android para selecionar imagens da galeria ou tirar uma nova foto com a câmera. Link

Obtido o Base64, o mesmo pode ser enviado no body de uma requisição post por exemplo.

Problemas com Base64

Respostas de API ficam muito grandes

Respostas muito grandes tendem a levar mais tempo para serem processadas dando mais tempo para uma possível falha na rede e aumentando o consumo de dados do dispositivo.

Oversizing

O tamanho da imagem codificada em Base64 é aproximadamente 30% maior do que a imagem binária original.

A experiência do usuário é afetada negativamente.

Incluindo os retornos junto com outras respostas da API, o aplicativo irá esperar carregar todos os dados antes de exibir informações na tela, afetando assim a experiência do usuário que verá uma tela de carregamento por mais tempo.

O armazenamento em cache de imagens no dispositivo não é mais possível.

Imagens enviadas para o dispositivo via Base64 tornará irrelevante qualquer implementação de serviços de cache de armazenamento de imagens.

Recursos nativos do flutter como o precacheImage tornam-se inutilizáveis nesta situação, já que toda vez será necessário fazer o decode do base64.

Outra implementação que se torna inutilizável seria o cachedNetworkImage, outra implementação nativa do flutter, mas que não pode ser aplicada ao contexto de um Base64.

Para aplicativos que possam funcionar tanto online quanto offline, a utilização de cache de imagens é um recurso bem eficaz para melhor experiência do usuário.

Vantagens do Base64

  • Remover a necessidade de múltiplos request, para obtenção de dados. ²
  • Imagens codificadas como Base64 podem ser armazenadas em bancos de dados e gerados novos arquivos. ² Como foi mostrado antes, essa abordagem pode ser uma vantagem ou uma desvantagem a depender do contexto e da implementação

Multipart Form Data

  • É uma de três formas de codificação existentes no HTML sendo elas:

1.application/x-www-form-urlencoded
2.multipart/form-data
3.text/plain

  • Deve-se utilizar esta forma de codificação quando a requisição possuir algum arquivo que deve fazer upload
  • É compatível com todos os navegadores.
  • Suporta arquivos com tamanhos muito grandes.

Utilizando multipart com Flutter

File file = await ImagePicker.pickImage(source: ImageSource.camera);
final multiPartdata = await MultipartFile.fromFile(file.path);
final formData = FormData.fromMap({
     "file": multiPartdata,
});
Enter fullscreen mode Exit fullscreen mode

Desta maneira o servidor da API deve estar preparado para receber requisições com o cabeçalho multipart/form-data, já que o conteúdo não irá junto com o body da requisição caso o mesmo exista.

Alguns servidores de storage como aws.s3, cloudinary, firebase cloud storage, estão preparados para receberem requisições nesse formato, possuindo libs para integração direta em Flutter, dispensando a necessidade da criação de uma api própria.

Resolvendo o Oversizing

Algumas estratégias podem ser admitidas a fim de reduzir o oversizing, a mais comum são os famosos thumbnails, algumas alternativas mais recentes que têm grande aplicabilidade a depender do contexto seriam o blurHash e a Dominant color abaixo explico o funcionamento de ambas.

Thumbnails

Uma thumbnail é uma imagem comprimida que prevê a imagem original. Elas são mais leves e podem ser utilizadas para diversos fins. Por exemplo, um dos propósitos da utilização dessa thumb é reduzir o tempo de carregamento de alguma pagina na internet, para tornar o acesso mais rápido ao usuário. Então, uma thumbnail de uma foto maior, seria uma versão reduzida dela mesma.

Em essência, a principal função de uma miniatura é trazer uma informação ao usuário de maneira mais rápida.

Blurhash

“BlurHash is a compact representation of a placeholder for an image”.

Blurhash é uma representação compacta de um espaço reservado para uma imagem. Esta é a definição dada pelos desenvolvedores. Trata-se de uma biblioteca que converte uma imagem para uma versão ofuscada e compactada de sua versão.
Essa biblioteca possui implementações para diversas linguagens, typescript, kotlin, swift, python, C, entre outras. Segue abaixo uma visão da mesma.

Dominant color

Trata-se apenas de pegar a cor de maior incidência na imagem, e utilizá-la no local da mesma. Estratégia bastante parecida com o blurHash, a diferença seria apenas o resultado final da imagem.

Referencial Bibliográfico

https://medium.com/snapp-mobile/dont-use-base64-encoded-images-on-mobile-13ddeac89d7c

https://pt.wikipedia.org/wiki/Base64

https://pub.dev/packages/image_picker

https://medium.com/snapp-mobile/dont-use-base64-encoded-images-on-mobile-13ddeac89d7c

http://www.coderiddles.com/base64-images/

https://neilpatel.com/br/blog/thumbnail-o-que-e/

https://github.com/woltapp/blurhash

https://lokeshdhakar.com/projects/color-thief/

https://flutter.dev/docs/cookbook/images/cached-images

Heroku

Deliver your unique apps, your own way.

Heroku tackles the toil — patching and upgrading, 24/7 ops and security, build systems, failovers, and more. Stay focused on building great data-driven applications.

Learn More

Top comments (0)

Retry later