API’s REST são muito legais para CRUD, mas e quando precisa fazer um Upload? Hoje veremos como enviar arquivos para uma API REST feita com NodeJs
O resultado final backend e frontend está disponível aqui: neste repositório do github.
Analisando a demanda
- Necessidade Permitir o envio de arquivos em uma API REST, com frontend independente, que poderia ser qualquer client, ou seja: FrontEND agnóstica.
Servidor básico
Poderiamos facilmente implementar em nossa API RESTfull com autenticação JSON Web Token JWT, mas para evitar confusão, vamos usar um servidor bem simples para este artigo.
Primeiro, crie uma pasta para seu projeto. Depois, crie os seguintes arquivos:
1 | { |
(Iremos usar o connect-multiparty
para receber o arquivo.)
Acesse a pasta com o terminal, e rode:1
npm install
Agora vamos criar o server. Ele é bem simples, e após o código explico o que está acontecendo:
1 | var express = require('express') |
No início, temos os vars e require()
, aí declaramos nossos middlewares do bodyParser.urlencoded()
e bodyParser.json()
. São o básico para uma API REST, sendo o primeiro para usar os URL params, e o segundo para .json()
., Aí a porta, o router e um app.use('/api')
que define nosso base endpoint.
Agora, criaremos nossa rota de upload. Insira, abaixo do comentário
1 | (...) |
Note a sintaxe do .post(multiparty(), require(....
.
O que isso quer dizer, é o middleware multiparty()
será executado antes de acessar o controller da rota, que iremos criar agora:
Criando o controller de Upload
Crie uma pasta chamada /controllers
.
Crie um arquivo upload.js
na pasta controllers
1 | var fs = require('fs'); |
Antes de tudo, no começo da função, res.setHeader("Access-Control-Allow-Origin", "*");
vai garantir que não tenhamos problemas com CORS, deixando claro que qualquer um pode fazer requests para essa rota. Não é a melhor prática do mundo, mas pra agora, nos serve.
Daí, usamos o fs
, módulo nativo do NodeJs.
O module.exports
contém nossa função.
Ela recebe 2 parâmetros: req
e res
, nossas conhecidas.
Na propriedade files
do objeto da requisição temos o nosso arquivo recebido pelo multiparty
.
Usamos a fs.rename()
para transferir ele da pasta temporária (req.files.file.path
) para uma nova que definimos na variável var novo
.
Se tiver erro, retorna res.status(500)
e a mensagem em JSON.
Se der tudo certo, res.json()
com o nome do arquivo.
Testando nosso server
Para testar, vá a pasta do server com o terminar e rode1
node server
Deu certo? Show! Agora vamos fazer o frontEnd.
Server pronto, vamos ao FrontEnd.
Crie uma outra pasta qualquer e crie um arquivo index.html
dentro dela.
1 |
|
Aqui, nada demais: um <input type="file"
com um ID e um <button>
com onClick=enviar()
, que é a função que vamos criar agora.
Crie o arquivo enviaArquivo.js
, e insira:
1 | function enviar(){ |
Aí é bem fácil:
var formData = new FormData()
… aí instanciamos um novo form, inserindo comappend()
um item chamado ‘file’ que vem dogetElementById("arquivoInput")
, o ID do nosso campo de arquivo no HTML.na
var xhr
criamos umnew XMLHttpRequest()
, que é a base do$ajax
, mas quis fazer sem JQuery esse exemplo (mandei mal? diga nos comentários!).Definimos como propriedade do
onreadystatechange
do XHR que criamos uma função. Ela vai testar sexhr.readyState == 4
. 4 significa concluído.
Se sim, inserimos a resposta (xhr.responseText
) no elemento#mensagem
do nosso HTML.Por último, abrimos a conexão com
xhr.open
, fazendo umPOST
para a url alí definida (no caso,localhost:8080
). Enviamos nosso formulário comxhr.send(formData)
.
Importante!!!
Não esqueça de criar a pasta /uploads
na raíz do seu projeto, senão vc receberá o erro:1
{"error":{"errno":34,"code":"ENOENT" .......
Testando nosso envio de arquivos com NodeJS
Rode o servidor pelo terminal com node server
(ou já deixou rodando? tanto faz ^_^) e abra o arquivo index.html
na raça mesmo, com 2 cliques. Tenta enviar um arquivo….
Viu a resposta? Maneiro né ^_^, enviamos nosso arquivo!
Para ver o arquivo, entre na pasta uploads
, criada agora na pasta do seu servidor.
Não deixamos a pasta uploads pública, por isso não dá para acessar pela URL.
Deixando a pasta uploads pública
Se quiser fazer isso, basta adicionar o seguinte, antes linha app.use('/api')
:
1 | app.use('/enviadas', express.static(__dirname + '/uploads')); |
Agora, acessando localhost:8080/enviadas/NOMEDOARQUIVO.ext
, você pode baixar o arquivo enviado.
Conclusão
É isso aí amiguinhos! Nossa brincadeira de hoje é muito útil, e facilmente implementável. O FrontEnd, reforçando, era só um exemplo. Você pode fazer o envio usando XTHMLRequests multipart
com qualquer frontend.
O resultado final deste artigo, backend e frontend, está disponível aqui: neste repositório do github.
Mais pra frente faremos algo mais bonitinho :)
Muito obrigado pela visita, e um grande abraço. Volte sempre. Keep Coding.
Ah, lembrando que agora temos Maillist. Cadastre seu e-mail na caixinha persistente ao lado –> e receba todo dia o post novo. Estou participando do #1postperday, brilhante iniciativa do @fdaciuk e tentarei fazer juz, produzindo bastante conteúdo legal
Comments