Skip to content

Instantly share code, notes, and snippets.

@rodrigogonn
Last active September 22, 2020 13:08
Show Gist options
  • Save rodrigogonn/6543b89391b6c8cbccba3bdd8de0630a to your computer and use it in GitHub Desktop.
Save rodrigogonn/6543b89391b6c8cbccba3bdd8de0630a to your computer and use it in GitHub Desktop.
Upload de arquivos no Node

Upload de arquivos no Node

Aqui vamos ver como enviar um formulário com arquivos e salvá-los no servidor.

Client side

No lado do cliente, vamos criar um formulário simples com alguns inputs no html:

<form>
  <label for="name"> Nome: </label>
  <input type="text" id="name" name="name" />
  
  <br /><br />
  
  <label for="photo"> Foto: </label>
  <input type="file" id="photo" name="photo" />
  
  <br /><br />
  
  <input type="submit" value="Enviar" />
</form>

image

Vamos capturar o evento de submit do formulário usando o javascript:

const form = document.querySelector('form');

form.addEventListener('submit', (event) => {
  event.preventDefault();
  
  // Código para enviar o formulário
}

Requisição com Fetch API

A Fetch API é fácil de utilizar e trabalha com promisses, então dá pra encadear as respostas e não transformar o código em uma pirâmide da desgraça.

fetch('http://localhost:3000/upload', {
  method: 'POST',
  body: new FormData(form),
})
.then((response) => {
  return response.text();
})
.then((data) => {
  console.log('Resposta:', data);
})
.catch((err) => {
  console.error(err);
});

image

Temos que colocar esse código dentro do event listener do formulário.

Requisição com XMLHttpRequest

XMLHttpRequest trabalha com eventos, mas também é uma opção boa, pois é possível capturar o progresso do upload, possibilitando criarmos uma barra de progresso ou algo do tipo.

const xhr = new XMLHttpRequest();

xhr.open('POST', 'http://localhost:3000/upload', true);

xhr.onload = () => {
  console.log('Resposta:', xhr.response, 'Status:', xhr.status);
};

xhr.onerror = (error) => {
  console.error(error);
};

xhr.upload.onprogress = (event) => {
  if (event.lengthComputable) {
    const completed = event.loaded / event.total;
    console.log(completed);
  }
};

xhr.upload.onloadstart = (event) => {
  console.log('Upload iniciado.');
};

xhr.upload.onloadend = (event) => {
  console.log('Upload concluído.');
};

xhr.send(new FormData(form));

image

Server side

No server vamos utilizar o formidable e o express.

Instalação:

npm install formidable express

Utilizando:

const express = require('express');
const formidable = require('formidable');
const fs = require('fs');
const path = require('path');

const app = express();

app.listen(3000, () => {
  console.log('Listening at port 3000.');
});

app.post('/upload', (req, res) => {
  const form = formidable.IncomingForm();

  form.parse(req, (err, fields, files) => {
    if (err) {
      res.status(500);
      res.send('Erro:', err);
      return;
    }

    if (files.photo) {
      const oldPath = files.photo.path;
      const newPath = path.join(__dirname, 'uploads', files.photo.name);

      fs.rename(oldPath, newPath, (error) => {
        if (error) throw error;
      });
    }
    res.send('Upload com sucesso!');
  });
});

Se o cliente enviou um imagem.png, por exemplo, ele será salvo em /uploads/imagem.png dentro do servidor nesse exemplo.

Aqui eu não usei o campo de nome do formulário que chegou, mas ele é acessível em fields.name.

Do photo eu só usei o name e path, mas também da pra usar size, type, hash, e lastModifiedDate.

Input com múltiplos arquivos

Para inputs do formulário que aceitam multiplos arquivos, como:

<input id="files" type="file" id="images" name="images" multiple />

image

Podemos utilizar o formidable desta forma:

app.post('/upload', (req, res) => {
    const form = formidable.IncomingForm();

    form.on('field', function (field, value) {
        console.log(`field: ${field} - ${value}`);
        // Código que faz algo com o field
    });

    form.on('file', function (field, file) {
        console.log(`file: ${field} - ${file.name}`);
        // Código que faz algo com o file
    });

    form.on('end', function () {
        console.log('Finish');
        res.send('Upload finalizado.');
    });

    form.parse(req);
});
field: name - Rodrigo
file: images - IMG_0004.jpg
file: images - IMG_0023.jpg
Finish
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment