Criar um backend de gerenciamento de mídia escalável: integrando Node.js, Armazenamento de blobs Azure e MongoDB
Tim Kelly10 min read • Published Dec 13, 2023 • Updated Nov 05, 2024
APLICATIVO COMPLETO
Avalie esse Tutorial
Se seu objetivo é desenvolver uma plataforma multimídia, um sistema robusto de gerenciamento de conteúdo ou qualquer tipo de aplicativo que exija o armazenamento de arquivos de mídia substanciais, o armazenamento, a recuperação e o gerenciamento desses arquivos são essenciais para oferecer uma experiência de usuário perfeita. É aqui que um back-end robusto de gerenciamento de mídia se torna um componente indispensável de sua pilha de tecnologia. Neste tutorial, guiaremos você pelo processo de criação de um back-end usando o Node.js, Armazenamento de blobs Azure e MongoDB.
Armazenar arquivos de mídia como imagens ou vídeos diretamente em seu MongoDB database pode não ser a abordagem mais eficiente. O MongoDB tem um limite de tamanho de documento BSON de 16MB, projetado para evitar que qualquer documento consuma muita RAM ou largura de banda durante a transmissão. Dado o tamanho de muitos arquivos de mídia, essa limitação pode ser facilmente excedida, apresentando um desafio significativo para armazenar arquivos grandes diretamente no banco de dados.
O GridFS do MongoDB é uma solução para armazenar arquivos grandes além do limite de tamanho do documento BSON, dividindo-os em partes e armazenando essas partes em documentos separados. Embora o GridFS seja uma solução viável para determinados cenários, uma abordagem eficiente é usar um serviço dedicado para armazenar arquivos de mídia grandes. O Armazenamento de Blobs do Azure ( objetos de trabalho secundários ), por exemplo, é otimizado para o armazenamento de quantidades substanciais de dados não estruturados, que incluem dados binários, como arquivos de mídia. Dados não estruturados referem-se a dados que não aderem a um modelo ou formato específico.
Forneceremos um plano para arquitetar um sistema de back-end capaz de lidar com armazenamento de mídia em grande escala com facilidade e mostraremos como publicá-lo usando comandos cURL. Ao final deste artigo, você terá uma compreensão clara de como aproveitar o Armazenamento de Blobs do Azure para lidar com grandes quantidades de dados não estruturados e o MongoDB para um gerenciamento eficiente de dados, tudo orquestrado com uma API Node.js que une tudo.
Se você é um desenvolvedor experiente ou está apenas começando, este guia foi desenvolvido para fornecer o conhecimento necessário para criar um back-end de gerenciamento de mídia que não seja apenas escalável, mas também otimizado para desempenho com esses arquivos grandes.
Primeiro, abordaremos os pré-requisitos necessários para este tutorial. Depois disso, prosseguiremos passo a passo para criar o back-end de um aplicativo robusto, eficiente e equipado para lidar com os requisitos de um aplicativo moderno e focado em mídia.
- Node.js 18 ou superior e npm: certifique-se de ter o Node.js e o npm (gerenciador de pacotes Node.js) instalados. O Node.js é o ambiente de execução necessário para executar seu código JavaScript no lado do servidor. npm é usado para gerenciar as dependências.
- Um cluster MongoDB implementado e configurado. Se precisar de ajuda, confira nosso tutorial do MongoDB Atlas sobre como começar.
Para este tutorial, usaremos o Microsoft Azure Portal para configurar nosso Azure storage. Comece fazendo login em sua Azure account e ela o levará à página inicial. Quando estiver lá, use a barra de pesquisa na parte superior da página para pesquisar "contas de armazenamento".
Selecione "Storage Accounts. " Evite selecionar "Storage accounts (classic) ", pois essa opção não possui todas as funcionalidades necessárias para esse tutorial.
Você será direcionado para uma página onde poderá criar uma nova conta de armazenamento ou utilizar uma existente. Neste tutorial, configuraremos a conta de armazenamento para que ela fique acessível publicamente por meio de sua URL. Embora essa configuração seja apropriada para uma demonstração, em um ambiente de produção, é crucial restringir o acesso a pessoas ou redes designadas por motivos de segurança. Instruções detalhadas sobre como configurar esses controles de acesso podem ser encontradas na documentação do Microsoft Azure.
Escolha sua assinatura e grupo de recursos preferidos e, em seguida, atribua um nome à sua conta de armazenamento. Embora a seleção das opções de região, desempenho e redundância varie de acordo com os requisitos do seu aplicativo, os níveis básicos serão suficientes para todas as funcionalidades exigidas neste tutorial.
Na seção de redes, opte por permitir o acesso público de todas as redes. Embora essa configuração geralmente não seja recomendada para ambientes de produção, ela simplifica o processo deste tutorial ao eliminar a necessidade de configurar regras específicas de acesso à rede.
Para o restante das definições de configuração, podemos aceitar as definições padrão. Depois que sua conta de armazenamento for criada, navegaremos até o recurso. Você pode fazer isso clicando em "Go to resource," ou retornar à página inicial e ela será listada em seus recursos.
Agora, criaremos um container. Pense em um container como um diretório em um sistema de arquivos, usado para organizar blobs. Você pode ter quantos container precisar em uma conta de armazenamento, e cada container pode conter vários blobs. Para isso, Go ao painel esquerdo e clique na aba container, depois escolha a opção "plus container ". Isso abrirá uma caixa de diálogo na qual você poderá nomear seu container e, se necessário, alterar o nível de acesso da configuração privada padrão. Depois de fazer isso, você pode Go e iniciar seu container.
Para conectar seu aplicativo ao Armazenamento Azure, você precisará criar um
Shared Access Signature
(SES). O SA fornece controle detalhado sobre como seu cliente pode acessar dados. No menu à esquerda, selecione "Shared access signature " e configure-o para permitir os serviços e tipos de recursos necessários. Para os fins deste tutorial, escolha "Object " em tipos de recursos permitidos, que é adequado para APIs em nível de blob e permite operações em blobs individuais, como upload, download ou exclusão.Você pode deixar as outras configurações com os valores padrão. No entanto, se você estiver interessado em entender quais configurações são ideais para seu aplicativo, a documentação da Microsoft oferece orientações abrangentes. Depois de finalizar suas configurações, clique em “Generate SAS and connection string.”. Esta ação produzirá seu SAS, exibido abaixo do botão.
Crie um .env no mesmo local em que você criará seu aplicativo para armazenar suas variáveis de ambiente. Adicione seu token Sas aqui. Também adicionaremos o nome da nossa conta de armazenamento e o nome do nosso contêiner. O nome da sua conta é exibido na parte superior da página de visão geral e o nome do contêiner pode ser encontrado clicando em "Container" no menu da folha à esquerda. Aqui você obterá uma lista de contêineres disponíveis para uso.
1 SAS_TOKEN="YOUR_SAS_TOKEN" 2 ACCOUNT_NAME="YOUR_ACCOUNT_NAME" 3 CONTAINER_NAME="YOUR_CONTAINER_NAME"
Tudo bem, vamos começar a conectar ao nosso armazenamento de blobs do Azure e ao MongoDB database. Para obter sua connection string do MongoDB, faça login no MongoDB Atlas e clique em conectar. Se precisar de ajuda, consulte nosso guia nos Docs.
Copie esta string e adicione-a ao arquivo .env com o nome
MONGODB_URI
.1 MONGODB_URI="mongodb+srv://<user>:<password>@<cluster>.mongodb.net/"
Para inicializar nosso projeto, usaremos o seguinte comando:
1 npm install --save @azure/storage-blob mongodb dotenv
Esse comando instalará o pacote
@azure/storage-blob
para interagir com o Azure Blob Storage, mongodb
para operações do MongoDB e dotenv
para carregar variáveis de ambiente.Vamos importar nossas dependências. No topo do nosso arquivo
app.mjs
, adicionaremos as seguintes linhas.1 import http from 'http'; 2 import { BlobServiceClient } from '@azure/storage-blob'; 3 import { MongoClient } from 'mongodb'; 4 import 'dotenv/config';
Abaixo disso, podemos configurar as variáveis de ambiente que usaremos e nos conectarmos ao Azure blob storage e ao MongoDB database.
1 // Load in environment variables 2 const mongodbUri = process.env.MONGODB_URI; 3 const accountName = process.env.ACCOUNT_NAME; 4 const sasToken = process.env.SAS_TOKEN; 5 const containerName = process.env.CONTAINER_NAME; 6 7 // Establishes a connection with Azure Blob Storage 8 const blobServiceClient = new BlobServiceClient(`https://${accountName}.blob.core.windows.net/?${sasToken}`); 9 const containerClient = blobServiceClient.getContainerClient(containerName); 10 11 // Connect to MongoDB 12 const client = new MongoClient(mongodbUri); 13 client.connect();
Precisamos estabelecer um lugar para fazer nossas chamadas de API. Vamos criar um novo servidor HTTP. O método http.createServer() faz parte do módulo HTTP do Node.js e usa uma função de ouvinte de solicitação como argumento. Nesse caso,
handleImageUpload
é passado como ouvinte de solicitações, o que significa que essa função será chamada toda vez que o servidor receber uma solicitação HTTP.1 const server = http.createServer(handleImageUpload); 2 const port = 3000; 3 server.listen(port, () => { 4 console.log(`Server listening on port ${port}`); 5 });
A função
handleImageUpload
foi projetada para processar solicitações HTTP POST para o endpoint /api/upload, gerenciando o upload de uma imagem e o armazenamento de seus metadados associados. Ele exigirá algumas funções auxiliares para conseguir isso. Veremos como eles também funcionam.1 async function handleImageUpload(req, res) { 2 res.setHeader('Content-Type', 'application/json'); 3 if (req.url === '/api/upload' && req.method === 'POST') { 4 try { 5 // Extract metadata from headers 6 const {fileName, caption, fileType } = await extractMetadata(req.headers); 7 8 // Upload the image as a to Azure Storage Blob as a stream 9 const imageUrl = await uploadImageStreamed(fileName, req); 10 11 // Store the metadata in MongoDB 12 await storeMetadata(fileName, caption, fileType, imageUrl); 13 14 res.writeHead(201); 15 res.end(JSON.stringify({ message: 'Image uploaded and metadata stored successfully', imageUrl })); 16 } catch (error) { 17 console.error('Error:', error); 18 res.writeHead(500); 19 res.end(JSON.stringify({ error: 'Internal Server Error' })); 20 } 21 } else { 22 res.writeHead(404); 23 res.end(JSON.stringify({ error: 'Not Found' })); 24 } 25 }
Se a solicitação recebida for um POST para o endpoint correto, ele chamará nosso método
extractMetadata
. Esta função pega nosso cabeçalho da solicitação e extrai os metadados associados.1 async function extractMetadata(headers) { 2 const contentType = headers['content-type']; 3 const fileType = contentType.split('/')[1]; 4 const contentDisposition = headers['content-disposition'] || ''; 5 const caption = headers['x-image-caption'] || 'No caption provided'; 6 const matches = /filename="([^"]+)"/i.exec(contentDisposition); 7 const fileName = matches?.[1] || `image-${Date.now()}.${fileType}`; 8 return { fileName, caption, fileType }; 9 }
Ele pressupõe que o cabeçalho 'content-type' da solicitação incluirá o tipo de arquivo (como image/png ou image/jpeg). Ele extrai esse tipo de arquivo do cabeçalho. Em seguida, ele tenta extrair um nome de arquivo do cabeçalho content-disposition, se fornecido. Se nenhum nome de arquivo for fornecido, ele gerará um padrão usando um carimbo de data/hora.
Usando o nome de arquivo extraído ou gerado e o tipo de arquivo, juntamente com o restante dos metadados do cabeçalho, ele chama
uploadImageStreamed
, que carrega a imagem como um fluxo diretamente da solicitação para o Azure Blob Storage.1 async function uploadImageStreamed(blobName, dataStream) { 2 const blobClient = containerClient.getBlockBlobClient(blobName); 3 await blobClient.uploadStream(dataStream); 4 return blobClient.url; 5 }
Nesse método, estamos criando nosso
blobClient
. O blobClient abre uma conexão com um blob de armazenamento do Azure e nos permite manipulá-lo. Aqui, carregamos nosso fluxo em nosso blob e, por fim, retornamos o URL do blob para ser armazenado no MongoDB.Quando tivermos nossa imagem armazenada no Azure Blob Storage, pegaremos a URL e a armazenaremos em nosso banco de dados. Os metadados que você decidir armazenar dependerão do seu aplicativo. Neste exemplo, adiciono uma legenda para o arquivo, o nome e o URL, mas você também pode querer informações como quem carregou a imagem ou quando ela foi carregada. Esse documento é inserido em uma coleção do MongoDB usando o método
storeMetadata
.1 async function storeMetadata(name, caption, fileType, imageUrl) { 2 const collection = client.db("tutorial").collection('metadata'); 3 await collection.insertOne({ name, caption, fileType, imageUrl }); 4 }
Aqui criamos e conectamos ao nosso MongoClient e inserimos nosso documento na coleção de metadados no tutorial. Não se preocupar se o banco de dados ou a collection ainda não existir. Assim que você tentar inserir dados, o MongoDB os criará.
Se o upload e o armazenamento de metadados forem bem-sucedidos, ele enviará de volta um código de status HTTP 201 e uma resposta JSON confirmando o sucesso do upload.
Agora temos uma chamada de API para carregar nossa imagem, juntamente com alguns metadados para essa imagem. Vamos testar o que criamos! Execute seu aplicativo executando o comando
node app.mjs
em um terminal que esteja aberto no diretório do aplicativo. Se estiver acompanhando o processo, substitua o caminho para a imagem abaixo pelo seu próprio caminho e pelo que deseja que os metadados sejam.1 curl -X POST \ 2 -H "Content-Type: image/png" \ 3 -H "Content-Disposition: attachment; filename=\"mongodb-is-webscale.png\"" \ 4 -H "X-Image-Caption: Your Image Caption Here" \ 5 --data-binary @"/path/to/your/mongodb-is-webscale.png" \ 6 http://localhost:3000/api/upload
Existem algumas etapas para nosso comando cURL.
curl -X POST
inicia uma solicitação curl usando o método POST, que é comumente usado para enviar dados para serem processados em um recurso especificado.-H "Content-Type: image/png"
inclui um cabeçalho na solicitação que informa ao servidor qual é o tipo do conteúdo que está sendo enviado. Nesse caso, indica que o arquivo que está sendo carregado é uma imagem PNG.-H "Content-Disposition: attachment; filename=\"mongodb-is-webscale.png\""
O cabeçalho é usado para especificar informações sobre o arquivo. Ele informa ao servidor que o arquivo deve ser tratado como um anexo, o que significa que deve ser baixado ou salvo em vez de exibido. O parâmetro filename é usado para sugerir um nome de arquivo padrão a ser usado se o conteúdo for salvo em um arquivo. (Caso contrário, nosso aplicativo gerará um automaticamente.)-H "X-Image-Caption: Your Image Caption Here"
header é usado para ditar nossa legenda. Após os dois pontos, inclua a mensagem que você deseja armazenar em ou documento MongoDB.--data-binary @"{Your-Path}/mongodb-is-webscale.png"
diz ao cURL para ler dados de um arquivo e preservar o formato binário dos dados do arquivo. O símbolo @ é usado para especificar que o que se segue é um nome de arquivo a partir do qual ler os dados. {Your-Path} deve ser substituído pelo caminho real para o arquivo de imagem que você estáenviando.http://localhost:3000/api/upload
é a URL para onde a solicitação está sendo enviada. Isso indica que o servidor está sendo executado no localhost (a mesma máquina da qual o comando está sendo executado) na porta 3000e o ponto de extremidade de API específico que manipula o upload é /api/upload.
Vamos ver como isso se parece em nosso armazenamento. Primeiro, vamos verificar nosso blob de armazenamento do Azure. Você pode visualizar a imagem
mongodb-is-webscale.png
acessando o container que criamos anteriormente. Ele confirma que a imagem foi armazenada com sucesso com o nome designado.Agora, como podemos recuperar esta imagem em nosso aplicação? Vamos verificar nosso banco de banco de dados MongoDB . Você pode fazer isso por meio do MongoDB Compass. Selecione o cluster e a collection para os quais você carregou seus metadados. Aqui você pode visualizar seu documento.
Você pode ver que armazenamos nossos metadados com sucesso! Se você seguir a URL, será direcionado para a imagem que carregou, armazenada em seu blob.
A integração do Armazenamento de Blobs do Azure com o MongoDB fornece uma solução ideal para armazenar arquivos de mídia grandes, como imagens e vídeos, e fornece uma estrutura sólida para criar seus aplicativos multimídia. O Azure Blob Storage, um serviço baseado em nuvem da Microsoft, se destaca no tratamento de grandes quantidades de dados não estruturados. Isso, combinado com o gerenciamento eficiente de banco de dados do MongoDB, cria um sistema robusto. Ele não apenas simplifica o processo de upload de arquivos, mas também gerencia com eficácia os metadados relevantes, oferecendo uma solução abrangente para as necessidades de armazenamento de dados.
Por meio deste tutorial, fornecemos a você as etapas para configurar um cluster do MongoDB Atlas e configurar o Azure Storage, e demonstramos como construir uma API do Node.js para interagir perfeitamente com ambas as plataformas.
Se seu objetivo é desenvolver uma plataforma multimídia, um sistema robusto de gerenciamento de conteúdo ou qualquer tipo de aplicativo que exija o armazenamento de arquivos de mídia substanciais, este guia oferece um caminho claro para embarcar nessa jornada. Utilizando as capacidades poderosas do Azure Blob Storage e do MongoDB, juntamente com uma API Node.js, os desenvolvedores têm as ferramentas para criar aplicativos que não são apenas escaláveis e eficientes, mas também robustos o suficiente para atender às necessidades do dinâmico ambiente web atual.
Quer saber mais sobre o que você pode fazer com o Microsoft Azure e o MongoDB? Confira alguns de nossos artigos no Centro de desenvolvedores, como Construir um site de notícias sobre criptografia em C# usando o Microsoft Azure App Service e o MongoDB Atlas, onde você pode aprender como criar e implantar um site em apenas algumas etapas simples.