Artigo original: GridFS Guide: How to Upload Files and Images to MongoDB Easily Using Node

Escrito por: Tarique Ejaz

O armazenamento de arquivos é um recurso importante e necessário em vários processos e em diversos tipos de aplicações. A existência de processos como as Content Delivery Networks (CDNs – ou, em português, redes de entrega de conteúdo), configuradas através de opções de nuvem de terceiros como a Amazon Web Services, e de opções de armazenamento de arquivos locais sempre tornaram mais fácil a criação desse tipo de recurso.

No entanto, o conceito de armazenar arquivos diretamente em um banco de dados através de uma única chamada de API me intriga há muito tempo. Foi aí que o GridFS entrou em cena para mim.

gridfs
Provavelmente, essa não é a melhor maneira de implementar um sistema de armazenamento de arquivos

O que é o GridFS – explicação simplificada

O MongoDB possui uma especificação de driver para upload e recuperação de arquivos chamada GridFS. O GridFS permite que você armazene e recupere arquivos, incluindo aqueles que excedem o limite de tamanho do documento BSON de 16 MB.

Basicamente, o GridFS pega um arquivo e o divide em vários pedaços, que são armazenados como documentos individuais em duas coleções:

  • a coleção chunk (que armazena as partes do documento) e
  • a coleção file (que armazena os metadados adicionais resultantes).

Cada pedaço (em inglês, chunk) é limitado a 255 KB de tamanho. Isso significa que o último pedaço é normalmente igual ou menor que 255 KB. Parece bom, não?

Quando você lê a partir do GridFS, o driver recompõe todos os pedaços conforme necessário. Isso significa que você pode ler seções de um arquivo de acordo com o intervalo de sua consulta. Um exemplo disso é quando você escuta um trecho de um arquivo de áudio ou busca uma seção de um arquivo de vídeo.

Observação: é preferível usar o GridFS para armazenar arquivos normalmente excedendo o limite de tamanho de 16 MB. Para arquivos menores, é recomendado usar o formato BinData para armazenar os arquivos em documentos únicos.

Isso resume como o GridFS funciona em geral. Hora de examinar um código funcionando e de ver como implementar um sistema assim.

Chega de papo, quero ver o código

Estamos usando o Node.js com acesso a uma instância de nuvem do MongoDB para nossa configuração. Você pode encontrar o repositório de código para a aplicação de exemplo aqui.

Vamos nos concentrar inteiramente em segmentos do código que se relacionam com as funcionalidades do GridFS. Vamos aprender como configurá-lo e usá-lo para armazenar arquivos, recuperar arquivos ou um arquivo específico e excluir um arquivo específico. Vamos começar.

Inicializando a engine de armazenamento

Os pacotes necessários para inicializar a engine são o multer-gridfs-storage e o multer. Também usamos o middleware method-override para habilitar a operação de exclusão de arquivos. O módulo crypto do npm é usado para criptografar os nomes dos arquivos ao serem armazenados e lidos do banco de dados.

Quando a engine de armazenamento usando GridFS é inicializada, você só precisa chamá-la usando o middleware multer. Ela é então passada para a rota respectiva que executa as várias operações de armazenamento de arquivos.

server-app-1

Inicializando o stream do GridFS

Inicializamos um stream do GridFS conforme visto no código abaixo. O stream é necessário para ler os arquivos do banco de dados e também para ajudar a renderizar uma imagem em um navegador quando necessário.

server-app-2

Fazendo o upload de um único arquivo ou imagem

Reutilizamos o middleware de upload que criamos anteriormente.

Observação: o nome file é usado como parâmetro em upload.single(), pois temos a chave com um nome similar carregando o arquivo que está sendo enviado pelo client.

server-app-4

Fazendo o upload de vários arquivos ou imagens

Também podemos fazer upload de vários arquivos de uma vez. Em vez de upload.single(), temos que simplesmente usar upload.multiple(<número de arquivos>).

Observação: o número de arquivos carregados pode ser menor que o número definido de arquivos.

server-app-5

Buscando todos os arquivos do banco de dados

Usando o stream inicializado, podemos buscar todos os arquivos no banco de dados específico usando gfs.find().toArray(...). Quando os arquivos são obtidos, mapeamos para um array e enviamos a resposta.

server-app-6

Buscando um único arquivo pelo nome do arquivo

É muito simples consultar o GridFS para um único arquivo baseado em um atributo específico, como filename (o nome do arquivo). Usando o stream do GridFS, você pode consultar o banco de dados através da função gfs.find({<adicione sua consulta aqui>}).

server-app-7

Renderizando no navegador uma imagem buscada

Essa é uma parte um pouco mais complicada, pois você precisa não apenas buscar um arquivo do banco de dados, mas também renderizá-lo como uma imagem no respectivo navegador. Buscamos o arquivo normalmente. Não há nada de novo nesse processo.

Então, com a ajuda do método openDownloadStreamByName() no stream do gfs, podemos facilmente renderizar uma imagem, pois ele retorna um stream legível. Tendo feito isso, podemos usar o método pipe() do JavaScript para transmitir a resposta.

Excluindo um arquivo específico por Id

Excluir um arquivo também é simples. Usamos o método delete() com o parâmetro _id para consultar e excluir o arquivo em questão.

server-app-9

Essas são as principais funcionalidades oferecidas pela engine de armazenamento. Eu utilizei os recursos do GridFS discutidos para criar uma aplicação simples de upload de imagens. Você pode ver o código em mais detalhes no repositório.

Conclusão

Demorei um pouco e tive uma quantidade razoável de dificuldade para entender como usar o GridFS para um projeto pessoal. Por causa disso, queria garantir que ao menos outra pessoa não precisasse ter de gastar a mesma quantidade de tempo que eu nisso.

Dito isso, eu recomendo usar o GridFS com cautela. Não é uma solução universal para todos os seus problemas de armazenamento de arquivos. Ainda assim, é interessante conhecer essa especificação e saber de sua existência.

Se você tiver alguma dúvida ou questão que deseje apontar, fique à vontade para entrar em contato com o autor pelo LinkedIn.

Boa programação para você! 🙂