Atualizado em 03/07/2024!
Eventualmente alguém me pergunta como fazer upload de arquivos em Node.js. Como é um assunto que já está na minha pauta há algum tempo, resolvi fazer este tutorial pra ajudar o pessoal. Você vai ver que não é algo muito difícil e este tutorial vai ser bem curto.
Parto do princípio aqui que você já sabe o básico de Node.js, JavaScript e de HTML, conhecimentos estes que podem ser obtidos em outros artigos aqui do blog, em meu livro, em meu curso ou até mesmo no meu canal do Youtube.
Vamos começar instalando o meu fork do express-generator, pacote que nos ajuda a criar aplicações web com ExpressJS, o mais famoso web framework para Node.js (você vai precisar de permissão de administrador no terminal de linha de comando):
1 2 3 |
npm install -g https://github.com/luiztools/express-generator.git |
Agora mande criar um novo projeto Express usando o comando abaixo, onde chamo o projeto de fileupload:
1 2 3 |
express --git fileupload |
Após entrar na pasta e instalar as dependências com npm install, instale a dependência formidable, que utilizaremos para lidar com o upload de arquivos em Node.js, dentre tantas alternativas existentes na Internet.
1 2 3 |
npm install formidable |
Agora vá na pasta views e abra o arquivo index.ejs para editarmos o HTML do projeto, deixando-o como abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!DOCTYPE html> <html> <head> <title><%= title %></title> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <h1><%= title %></h1> <p>Welcome to <%= title %></p> <form action="/" method="post" enctype="multipart/form-data"> <input type="file" name="filetoupload"><br> <input type="submit"> </form> </body> </html> |
Note que não tem nada demais aqui, apenas um formulário com um campo de upload de arquivo, mas repare que o formulário possui o enctype como multipart/form-data, isso é muito importante para que upload funcione!
Se você executar esta aplicação com npm start verá algo como abaixo:
Agora vamos programar o comportamento desta página. Fazemos isso indo na pasta routes e abrindo o arquivo index.js, onde temos as rotas da tela inicial.
Adicione a nova rota abaixo dentro deste arquivo:
1 2 3 4 5 6 7 8 9 |
router.post('/', (req, res, next) => { const formidable = require('formidable'); const form = new formidable.IncomingForm(); form.parse(req, (err, fields, files) => { res.send('File uploaded'); }); }); |
O que fazemos aqui?
Carregamos a extensão formidable que instalamos há pouco, recebemos o form POSTado pelo usuário e salvamos o arquivo através da função form.parse. Se você testar agora já deve estar funcionando.
Mas…onde que o arquivo foi salvo?
Por padrão ele fica salvo em uma pasta temporária no seu computador. Para mudar isso, vamos modificar nosso código anterior para que usando a biblioteca fs (file system) do Node possamos mover o arquivo que fizemos upload para a mesma pasta do seu projeto:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
router.post('/', (req, res, next) => { const formidable = require('formidable'); const fs = require('fs'); const form = new formidable.IncomingForm(); form.parse(req, (err, fields, files) => { const path = require('path'); const oldpath = files.filetoupload.path; const newpath = path.join(__dirname, '..', files.filetoupload.name); fs.renameSync(oldpath, newpath); res.send('File uploaded and moved!'); }); }); |
Note que carreguei o módulo fs lá no início do código e que depois uso este módulo para mover o arquivo de lugar no sistema operacional usando a função renameSync (que dispensa o uso de callbacks e promises). Para definir ONDE é este lugar de destino, usei o path.join para montar um caminho contendo o __dirname (pasta atual deste módulo), voltar uma pasta (..) e com isso chegar na raiz do projeto.
Já o arquivo que fiz upload é facilmente encontrado usando o argumento files, que é o terceiro da função form.parse.
O resultado na tela é esse:
Mas no seu computador o arquivo que você fez o upload estará disponível na pasta raiz do seu projeto.
Fácil, não é?!
Bônus: Mais uma opção
Agora caso tenha problemas com o formidable (eu nunca tive), você pode usar a dependência Multer:
1 2 3 |
npm i multer |
E uma forma de utilizá-lo é essa:
1 2 3 4 5 6 7 8 9 10 11 |
const multer = require('multer'); // cria uma instância do middleware configurada const upload = multer({ dest: 'uploads/' }); // rota indicado no atributo action do formulário router.post('/', upload.single('file'), (req, res, next) => { res.send('<h2>Upload realizado com sucesso</h2>') }); |
Você pode usar o código acima reaproveitando a mesma view do exemplo anterior e o arquivo será salvo com nome aleatório na pasta uploads, na raiz do seu projeto.
Além disso, convém você não deixar os seus arquivos no mesmo servidor da aplicação. Para upload para serviços de armazenamento em nuvem, recomendo o AWS S3. Uma solução mais simples e barata pode ser o Google Drive.
Espero ter ajudado!
Curtiu este tutorial? Conheça o meu curso online de Node.js e MongoDB para fazer aplicações web e APIs incríveis com esta fantástica plataforma. Basta clicar no banner abaixo!
Olá, tudo bem?
O que você achou deste conteúdo? Conte nos comentários.