1. Code
  2. JavaScript
  3. Node

Subir archivos con Multer en Node.js y Express

Cuando un cliente web sube un archivo a un servidor, generalmente lo envía a través de un formulario y se codifica como multipart/form-data. Multer es un middleware para Express y Node.js que hace que sea fácil manipular este multipart/form-data cuando tus usuarios suben archivos.
Scroll to top

Spanish (Español) translation by Ruben Solis (you can also view the original English article)

Cuando un cliente web sube un archivo a un servidor, generalmente lo envía a través de un formulario y se codifica como multipart/form-data. Multer es un middleware para Express y Node.js que hace que sea fácil manipular este multipart/form-data cuando tus usuarios suben archivos.

En este tutorial, te mostraré cómo usar la biblioteca Multer para manejar diferentes situaciones de carga de archivos en Node.

¿Cómo funciona Multer?

Como dije anteriormente, Multer es un middleware para Express. Un middleware es una pieza de software que conecta diferentes aplicaciones o componentes de software. En Express, un middleware procesa y transforma las peticiones entrantes en el servidor. En nuestro caso, Multer actúa como un ayudante al cargar archivos.

Configuración del proyecto

Utilizaremos el framework para Node llamado Express para este proyecto. Por supuesto, necesitarás tener Node instalado.

Crea un directorio para nuestro proyecto, navega en el directorio y teclea npm init para crear un archivo .json que administre todas las dependencias de nuestra aplicación.

1
mkdir upload-express
2
cd  upload-express
3
npm init

A continuación, instala Multer, Express y las demás dependencias necesarias para iniciar una aplicación Express.

1
npm install express multer body-parser --save

A continuación, crea un archivo server.js.

1
touch server.js

Luego, en server.js, inicializaremos todos los módulos, crearemos una aplicación Express y crearemos un servidor para conectarse a los navegadores.

1
// call all the required packages

2
const express = require('express')
3
const bodyParser= require('body-parser')
4
const multer = require('multer');
5
app.use(bodyParser.urlencoded({extended: true}))
6
7
const app = express()
8
9
//CREATE EXPRESS APP

10
const app = express();
11
12
//ROUTES WILL GO HERE

13
app.get('/', function(req, res) {
14
    res.json({ message: 'WELCOME' });   
15
});
16
17
app.listen(3000, () => console.log('Server started on port 3000'));

Ejecutar node server.js y navegar a localhost: 3000 en tu navegador debería darte el siguiente mensaje.

welcome messagewelcome messagewelcome message

Crear el código del cliente

Lo siguiente será crear un archivo index.html para escribir todo el código que se servirá al cliente.

1
touch index.html

Este archivo contendrá los diferentes formularios que utilizaremos para cargar nuestros diferentes tipos de archivos.

1
<!DOCTYPE html>
2
<html lang="en">
3
<head>
4
  <meta charset="UTF-8">
5
  <title>MY APP</title>
6
</head>
7
<body>
8
  
9
10
 <!--  SINGLE FILE -->
11
<form action="/uploadfile" enctype="multipart/form-data" method="POST"> 
12
   <input type="file" name="myFile" />
13
   <input type="submit" value="Upload a file"/>
14
</form>
15
16
17
<!-- MULTIPLE FILES -->
18
19
<form action="/uploadmultiple"  enctype="multipart/form-data" method="POST">
20
  Select images: <input type="file" name="myFiles" multiple>
21
  <input type="submit" value="Upload your files"/>
22
</form>
23
24
  <!--   PHOTO-->
25
26
<form action="/upload/photo" enctype="multipart/form-data" method="POST"> 
27
  <input type="file" name="myImage" accept="image/*" />
28
  <input type="submit" value="Upload Photo"/>
29
</form>
30
31
32
33
</body>
34
</html>
35

Abre server.js y escribe una ruta GET que muestre el archivo index.html en lugar del mensaje "WELCOME" ("BIENVENIDO", en español).

1
// ROUTES

2
app.get('/',function(req,res){
3
  res.sendFile(__dirname + '/index.html');
4
5
});

Almacenamiento con Multer

Lo siguiente será definir una ubicación de almacenamiento para nuestros archivos. Multer ofrece la opción de almacenar archivos en el disco, como se muestra a continuación. Aquí, configuramos un directorio donde se guardarán todos nuestros archivos, y también les daremos a los archivos un nuevo identificador.

1
//server.js
2
3
4
// SET STORAGE
5
var storage = multer.diskStorage({
6
  destination: function (req, file, cb) {
7
    cb(null, 'uploads')
8
  },
9
  filename: function (req, file, cb) {
10
    cb(null, file.fieldname + '-' + Date.now())
11
  }
12
})
13
14
var upload = multer({ storage: storage })

Manejo de carga de archivos

Subiendo un solo archivo

En el archivo index.html, definimos un atributo de acción que realiza una petición POST. Ahora necesitamos crear un punto final en la aplicación Express. Abre el archivo server.js y agrega el siguiente código:

1
app.post('/uploadfile', upload.single('myFile'), (req, res, next) => {
2
  const file = req.file
3
  if (!file) {
4
    const error = new Error('Please upload a file')
5
    error.httpStatusCode = 400
6
    return next(error)
7
  }
8
    res.send(file)
9
 
10
})

Ten en cuenta que el name (nombre, en español) del campo archivo debe ser el mismo que el argumento myFile pasado a la función upload.single.

Subiendo múltiples archivos

Cargar varios archivos con Multer es similar a cargar un solo archivo, pero con algunos cambios.

1
//Uploading multiple files

2
app.post('/uploadmultiple', upload.array('myFiles', 12), (req, res, next) => {
3
  const files = req.files
4
  if (!files) {
5
    const error = new Error('Please choose files')
6
    error.httpStatusCode = 400
7
    return next(error)
8
  }
9
10
    res.send(files)
11
 
12
})

Subiendo Imágenes

En lugar de guardar las imágenes cargadas en el sistema de archivos, las almacenaremos en una base de datos MongoDB para poder recuperarlas más tarde según sea necesario. Pero primero, instalemos MongoDB.

1
npm install mongodb --save

Luego nos conectaremos a MongoDB a través del método Mongo.client y luego agregaremos la URL de MongoDB a ese método. Puedes usar un servicio en la nube como Mlab, que ofrece un plan gratuito, o simplemente usar la conexión disponible localmente.

1
const MongoClient = require('mongodb').MongoClient
2
const myurl = 'mongodb://localhost:27017';
3
4
MongoClient.connect(myurl, (err, client) => {
5
  if (err) return console.log(err)
6
  db = client.db('test') 
7
  app.listen(3000, () => {
8
    console.log('listening on 3000')
9
  })
10
})

Abre server.js y define una petición POST que permita guardar imágenes en la base de datos.

1
app.post('/uploadphoto', upload.single('picture'), (req, res) => {
2
    var img = fs.readFileSync(req.file.path);
3
 var encode_image = img.toString('base64');
4
 // Define a JSONobject for the image attributes for saving to database

5
 
6
 var finalImg = {
7
      contentType: req.file.mimetype,
8
      image:  new Buffer(encode_image, 'base64')
9
   };
10
db.collection('quotes').insertOne(finalImg, (err, result) => {
11
  	console.log(result)
12
13
    if (err) return console.log(err)
14
15
    console.log('saved to database')
16
    res.redirect('/')
17
  
18
    
19
  })
20
})

En el código anterior, primero codificamos la imagen en una cadena base64, construimos un nuevo búfer a partir de la cadena codificada en base64 y luego la guardamos en nuestra colección de base de datos en formato JSON.

Luego mostramos un mensaje de éxito y redirigimos al usuario a la página de inicio.

Recuperando imágenes almacenadas

Para recuperar las imágenes almacenadas, realizamos una búsqueda en MongoDB utilizando el método find y devolvemos un arreglo de resultados. Luego continuamos y obtenemos los atributos _id de todas las imágenes y las devolvemos al usuario.

1
app.get('/photos', (req, res) => {
2
db.collection('mycollection').find().toArray((err, result) => {
3
4
      const imgArray= result.map(element => element._id);
5
			console.log(imgArray);
6
7
   if (err) return console.log(err)
8
   res.send(imgArray)
9
10
  })
11
});

Como ya conocemos los id's de las imágenes, podemos ver una imagen pasando su id en el navegador, como se ilustra a continuación.

1
app.get('/photo/:id', (req, res) => {
2
var filename = req.params.id;
3
4
db.collection('mycollection').findOne({'_id': ObjectId(filename) }, (err, result) => {
5
6
    if (err) return console.log(err)
7
8
   res.contentType('image/jpeg');
9
   res.send(result.image.buffer)
10
  
11
   
12
  })
13
})
Saved imageSaved imageSaved image

Conclusión

Espero que hayas encontrado útil este tutorial. La carga de archivos puede ser un tema intimidante, pero no tiene que ser difícil de implementar. Con Express y Multer, manejar multipart/form-data es fácil y directo.

Puedes encontrar el código fuente completo para el ejemplo de carga de archivos en nuestro repositorio de GitHub.