Download Eficiente de Arquivos Grandes no Node.js com Fetch e Streams
Fazer download de arquivos volumosos carregando todo o conteúdo na memória RAM antes de salvar no disco pode travar a aplicação e causar estouro de memória (out of memory). O uso da API nativa fetch combinada com ReadableStream do Node.js e fs.createWriteStream resolve esse gargalo ao transferir o arquivo em fluxo contínuo diretamente para o sistema de arquivos.
JavaScript
const fs = require('fs');
const { pipeline } = require('stream/promises');
/**
* Realiza o download de um arquivo via stream e o salva diretamente no disco.
* @param {string} url - URL do arquivo a ser baixado.
* @param {string} caminhoDestino - Caminho local onde o arquivo será salvo.
*/
async function baixarArquivoComStream(url, caminhoDestino) {
const resposta = await fetch(url);
// Valida se a requisição HTTP foi bem-sucedida
if (!resposta.ok) {
throw new Error(`Falha ao baixar arquivo: ${resposta.status} ${resposta.statusText}`);
}
// Obtém a stream de leitura do corpo da resposta e cria a stream de escrita no disco
const streamLeitura = resposta.body;
const streamEscrita = fs.createWriteStream(caminhoDestino);
// Conecta a stream de entrada diretamente ao arquivo de destino
await pipeline(streamLeitura, streamEscrita);
console.log(`[Sucesso] Download concluído e salvo em: ${caminhoDestino}`);
}
// --- Exemplo Prático de Uso ---
(async () => {
const urlExemplo = 'https://httpbin.org/bytes/102400'; // Gera um arquivo de teste de ~100KB
const destino = './arquivo_baixado.bin';
try {
console.log('Iniciando o download do arquivo...');
await baixarArquivoComStream(urlExemplo, destino);
} catch (erro) {
console.error('Erro durante o download:', erro.message);
}
})();
Pontos-chave
- Consumo Baixo e Constante de RAM: A transferência ocorre em chunks (pequenos blocos de dados), garantindo uso mínimo de memória mesmo ao baixar arquivos de múltiplos gigabytes.
- Uso da API
fetchNativa: A solução utiliza a APIfetchintegrada a partir do Node.js v18+, eliminando a necessidade de dependências externas comoaxiosougot. - Gerenciamento de Recursos com
pipeline: A funçãostream/promises.pipelinegarante o fechamento automático de todas as streams e a remoção de descritores de arquivo abertos caso ocorra uma falha na rede. - Tratamento do Corpo da Resposta: A propriedade
resposta.bodyretorna uma instância compatível comReadableStream, pronta para ser consumida e encadeada em streams graváveis do Node.js.
