Upload file con NodeJS ed Express

Breve appunto su come realizzare un semplice form per caricare un file su un server realizzato con NodeJS ed Express. Realizzere un semplice server che serve una pagina statica HTML con un form di upload e un unico endpoint per gestire la ricezione del file. Il codice di esempio descritto in questo post è scaricabile dal repository git.

Per prima cosa spostiamoci nella cartella di lavoro e inizializziamo il progetto con npm:

npm init --yes

Modifichiamo il file package.json per aggiungere, nell'oggetto root, l'opzione che consente di utilizzare nei file javascript le dipendenze con la sintassi "import":

"type": "module"

Installiamo le dipendenze:

npm install express express-fileupload morgan body-parser

Adesso creiamo una cartella src, e dentro questa il file index.js. Dentro il file, per prima cosa, importiamo le dipendenze necessarie:

import express from 'express';
import fileUpload from 'express-fileupload';
import bodyParser from 'body-parser';
import morgan from 'morgan'; // Stampa log HTTP
import fs from 'fs';

Inizializziamo il server Express:

// Inizializzazione express.
const app = express();

// Abilitazione upload file.
// (specificare il nome della cartella temporanea da usare)
app.use(fileUpload({
  createParentPath: true,
  useTempFiles : true,
  tempFileDir : './tmp/'	
}));

// Abilitazione middleware.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(morgan('dev'));

// Serviamo il contenuto di public come risorse statiche.
app.use(express.static('public'));

// Avvio server.
const port = process.env.PORT || 3000;
app.listen(port, () => 
  console.log(`App is listening on port ${port}.`)
);

A questo punto possiamo creare un endpoint per l'upload, comodamente denominato /upload. Questo endpoint si aspetta di ricevere il file all'interno di un form HTML, in un oggetto denominato "nuovoFile":

app.post('/upload', async (req, res) => {

  if(!req.files) {	
    res.send({
      message: 'Errore: nessun file caricato'
    });
  }
  else {
    
    // Path del file caricato nella cartella temporanea
    let tempFilePath = req.files.nuovoFile.tempFilePath;
        
    // qui possiamo utilizzare il file, accedendo al
    // path definito in tempFilePath	
    console.log(`File caricato con successo: ${tempFilePath}`)
    // ...
        
    // Risposta al browser
    res.send({
      message: 'Caricamento effettuato con successo.'
    })
                
  }
   
});

Per concludere, creiamo un file statico HTML contenente il form. Nella root del progetto creiamo una cartella public (o il percorso specificato durante l'inizializzazione del server), e dentro questa creiamo il file index.html:

<html>
<head>
  <title>Prova caricamento file</title>
</head>
<body>
  <h1>Prova caricamento file</h1>
  <form action="/upload" enctype="multipart/form-data" method="post">
    <input type="file" id="nuovoFile" name="nuovoFile"><br/>
    <input type="submit">
  </form>	
</body>
</html>

Proviamo

A questo punto possiamo avviare il server node:

node src/index.js

Aprendo con il browser l'indirizzo http://localhost:5000 dovremmo vedere il form.

Selezioniamo un file, premiamo il pulsante di conferma e il browser dovrebbe mostrare il messaggio di conferma.

A questo punto andiamo a vedere nella cartella tmp/ del nostro progetto e troveremo lì il nostro file (con il nome alterato).

L'output dell'applicazione dovrebbe confermare l'avvenuta gestione del file.

Fatto!