Système de fichiers
Le module fs
Node.js embarque en natif le module fs (File System) qui donne accès au système
de fichiers du serveur : lecture, écriture, suppression, liste de dossiers, etc.
Aucune installation nécessaire — il fait partie de la bibliothèque standard de Node.
Il existe trois façons d'utiliser fs selon le style de code que tu préfères :
- Synchrone — bloque l'exécution jusqu'à la fin de l'opération (
fs.readFileSync) - Callbacks — style Node.js historique, n'attend pas (
fs.readFile) - Promesses — style moderne avec
async/awaitviafs/promises
// Import façon CommonJS (la plus courante dans Node.js)
const fs = require('fs');
// Import de la version promesses (recommandé pour le code moderne)
const fs = require('fs/promises');
// Import ES Modules (si "type": "module" dans package.json)
import fs from 'fs/promises';
Lire un fichier
Trois syntaxes pour lire un fichier. Le résultat est un Buffer par défaut ;
passe 'utf8' pour obtenir directement une chaîne de caractères.
const fs = require('fs');
// 1. Callback — non-bloquant, résultat dans la fonction
fs.readFile('notes.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
// 2. Synchrone — bloque jusqu'à la fin (à éviter dans un serveur)
const contenu = fs.readFileSync('notes.txt', 'utf8');
console.log(contenu);
// 3. Promesses — moderne, compatible async/await
const fsp = require('fs/promises');
async function lireFichier() {
const contenu = await fsp.readFile('notes.txt', 'utf8');
console.log(contenu);
}
lireFichier();
Préfère fs/promises avec async/await dans tout nouveau code.
C'est plus lisible, plus facile à déboguer et s'intègre parfaitement avec Express et les autres API modernes de Node.js.
Écrire un fichier
writeFile crée le fichier s'il n'existe pas ou le remplace entièrement.
Pour ajouter du contenu à la fin sans effacer l'existant, utilise appendFile.
const fsp = require('fs/promises');
async function ecrire() {
// Crée ou remplace le fichier
await fsp.writeFile('journal.txt', 'Bonjour !\n', 'utf8');
// Ajoute une ligne à la fin sans effacer le contenu existant
await fsp.appendFile('journal.txt', 'Nouvelle entrée\n', 'utf8');
console.log('Fichier écrit !');
}
ecrire();
Vérifier l'existence d'un fichier
Avant de lire ou d'écrire, il est souvent utile de vérifier si un fichier existe.
existsSync est simple mais synchrone. stat donne des informations détaillées
(taille, date, type) de façon asynchrone.
const fs = require('fs');
const fsp = require('fs/promises');
// Synchrone — retourne true ou false
if (fs.existsSync('config.json')) {
console.log('Le fichier existe');
}
// Stat — donne taille, dates, type (fichier ou dossier ?)
async function infos() {
try {
const stats = await fsp.stat('config.json');
console.log('Taille :', stats.size, 'octets');
console.log('C\'est un dossier ?', stats.isDirectory());
console.log('Modifié le :', stats.mtime);
} catch (err) {
console.log('Fichier introuvable');
}
}
infos();
Lister un dossier
readdir retourne un tableau contenant le nom de tous les fichiers
et sous-dossiers présents dans un répertoire.
const fsp = require('fs/promises');
async function listerDossier() {
const fichiers = await fsp.readdir('./uploads');
console.log(fichiers);
// ['image.png', 'document.pdf', 'notes.txt']
// Pour avoir aussi le type (fichier / dossier)
const details = await fsp.readdir('./uploads', { withFileTypes: true });
details.forEach(entry => {
const type = entry.isDirectory() ? 'dossier' : 'fichier';
console.log(`${entry.name} — ${type}`);
});
}
listerDossier();
Créer et supprimer
mkdir crée un dossier. L'option recursive: true crée tous les
intermédiaires manquants sans erreur si le dossier existe déjà.
rm supprime un fichier ou un dossier entier. unlink ne supprime que des fichiers.
const fsp = require('fs/promises');
// Créer un dossier (recursive = ne plante pas si existe déjà)
await fsp.mkdir('./uploads/images', { recursive: true });
// Supprimer un fichier
await fsp.unlink('./uploads/ancien.jpg');
// Supprimer un dossier et tout son contenu (recursive)
await fsp.rm('./uploads/temp', { recursive: true, force: true });
// Renommer ou déplacer un fichier
await fsp.rename('./old-name.txt', './new-name.txt');
fs.rm avec recursive: true supprime définitivement tout le contenu du dossier,
sans passer par la corbeille. Assure-toi de bien viser le bon chemin avant d'exécuter cette commande.
Streams : lire les gros fichiers
Pour les fichiers volumineux (logs, vidéos, exports CSV…), charger tout le contenu en mémoire
avec readFile peut saturer le serveur. Les streams lisent le fichier
par morceaux (chunks) au fur et à mesure, sans tout charger d'un coup.
const fs = require('fs');
// Créer un flux de lecture
const stream = fs.createReadStream('./gros-fichier.csv', { encoding: 'utf8' });
// Chaque morceau arrive ici
stream.on('data', (chunk) => {
console.log('Reçu :', chunk.length, 'caractères');
});
stream.on('end', () => {
console.log('Lecture terminée');
});
stream.on('error', (err) => {
console.error('Erreur :', err.message);
});
// Astuce : piper directement vers une réponse HTTP
// stream.pipe(res); — envoie le fichier au client sans tout charger
Le module path
Le module path aide à construire des chemins de fichiers de façon fiable,
quel que soit l'OS (Windows utilise \, Linux/Mac utilisent /).
Il fait aussi partie de la bibliothèque standard de Node.js.
const path = require('path');
// __dirname = dossier du fichier actuel (chemin absolu)
console.log(__dirname);
// /home/user/monapp/src
// path.join — assemble des segments de chemin intelligemment
const chemin = path.join(__dirname, 'data', 'users.json');
// /home/user/monapp/src/data/users.json
// path.resolve — chemin absolu depuis n'importe où
const absolu = path.resolve('config.json');
// /home/user/monapp/config.json (résolu depuis le dossier courant)
// path.extname — extension du fichier
path.extname('photo.jpg'); // '.jpg'
path.extname('archive.tar.gz'); // '.gz'
// path.basename — nom du fichier sans le chemin
path.basename('/data/users.json'); // 'users.json'
path.basename('/data/users.json', '.json'); // 'users'
// path.dirname — dossier parent d'un chemin
path.dirname('/data/users.json'); // '/data'
Utilise toujours path.join(__dirname, ...) plutôt que de concaténer des chaînes
manuellement (__dirname + '/data/' + fichier). path.join gère les séparateurs
selon l'OS et évite les doubles slashes.
require('fs/promises')+async/awaitest l'approche recommandée pour le code moderne.readFilelit,writeFileécrase,appendFileajoute,unlinksupprime un fichier.existsSyncvérifie l'existence en synchrone ;statdonne les détails en asynchrone.mkdir({ recursive: true })crée un dossier sans planter si les parents existent déjà.- Pour les gros fichiers, utilise
createReadStreampour éviter de saturer la mémoire. path.join(__dirname, ...)pour construire des chemins portables selon l'OS.