Télécharger des fichiers depuis le web en Node.js

Quelle que soit l’application sur laquelle on travaille, il arrive forcement un moment ou cette dernière doit automatiquement télécharger des ressources web. Des images de profil téléchargées depuis Gravatar ou Twitter par exemple. Voyons comment créer rapidement une fonction de téléchargement.

Il existe un module fort pratique pour nous aider dans notre tâche, j’ai nommé request, un client http. Néanmoins, nous ajouterons aussi une manière native, qui ne dépende d’aucun module externe à node.

Télécharger un fichier avec request

Commençons par la première méthode, avec le module request, car elle est plus souple. On commence bien entendu par installer request dans le projet avec npm install --save request. C’est parti !

Dans le mesure où on est en nodejs et pas dans un navigateur, j’utilise ici directement du code en ES6. Le code est suffisamment commenté pour que vous puissiez comprendre.

// on récupère les modules nécessaires
const fs = require('fs');
const request = require('request');

function download(url, dest, cb) {
  // on créé un stream d'écriture qui nous permettra
  // d'écrire au fur et à mesure que les données sont téléchargées
  const file = fs.createWriteStream(dest);

  // on lance le téléchargement
  const sendReq = request.get(url);

  // on vérifie la validité du code de réponse HTTP
  sendReq.on('response', (response) => {
    if (response.statusCode !== 200) {
      cb('Response status was ' + response.statusCode);
    }
  });

  // au cas où request rencontre une erreur
  // on efface le fichier partiellement écrit
  // puis on passe l'erreur au callback
  sendReq.on('error', (err) => {
    fs.unlink(dest);
    cb(err.message);
  });

  // écrit directement le fichier téléchargé
  sendReq.pipe(file);

  // lorsque le téléchargement est terminé
  // on appelle le callback
  file.on('finish', () => {
    // close étant asynchrone,
    // le cb est appelé lorsque close a terminé
    file.close(cb);
  });

  // si on rencontre une erreur lors de l'écriture du fichier
  // on efface le fichier puis on passe l'erreur au callback
  file.on('error', (err) => {
    // on efface le fichier sans attendre son effacement
    // on ne vérifie pas non plus les erreur pour l'effacement
    fs.unlink(dest);
    cb(err.message);
  });
};

Simple et efficace n’est-ce pas ? Vous passez donc à cette fonction une url, un fichier de destination et un callback afin de savoir quand c’est terminé et s’il y a eu des erreurs. Voici comment l’utiliser :

download('https://buzut.fr/wp-content/themes/buzut-theme/img/logo.jpg', '/var/www/files/buzut-logo.jpg', (err) => {
  if (err) {
    console.error(err);
    return;
  }

  console.log('Téléchargement terminé !');
})

Télécharger un fichier sans aucune dépendance

Le code reste ici assez similaire. On va utiliser le module http ou https au lieu d’utiliser request.

// on récupère les modules nécessaires
var fs = require('fs');
var http = require('http');
var https = require('https');

function download(url, dest, cb) {
  // on créé un stream d'écriture qui nous permettra
  // d'écrire au fur et à mesure que les données sont téléchargées
  const file = fs.createWriteStream(dest);
  let httpMethod;

  // afin d'utiliser le bon module on vérifie si notre url
  // utilise http ou https
  if (url.indexOf(('https://')) !== -1) httpMethod = https;
  else httpMethod = http;

  // on lance le téléchargement
  const request = httpMethod.get(url, (response) => {
    // on vérifie la validité du code de réponse HTTP
    if (response.statusCode !== 200) {
      cb('Response status was ' + response.statusCode);
    }

    // écrit directement le fichier téléchargé
    response.pipe(file);

    // lorsque le téléchargement est terminé
    // on appelle le callback
    file.on('finish', () => {
      // close étant asynchrone,
      // le cb est appelé lorsque close a terminé
      file.close(cb);
    });
  });

  // check for request error too
  request.on('error', (err) => {
    fs.unlink(dest);
    cb(err.message);
  });

  // si on rencontre une erreur lors de l'écriture du fichier
  // on efface le fichier puis on passe l'erreur au callback
  file.on('error', (err) => {
    // on efface le fichier sans attendre son effacement
    // on ne vérifie pas non plus les erreur pour l'effacement
    fs.unlink(dest);
    cb(err.message);
  });
};

Et voilà pour la méthode native. Elle s’utilise exactement de la même manière que l’autre fonction.

Vous noterez que dans notre cas, il n’y a pas une grande différence entre les deux fonctions. Le module request trouve tout son intérêt dès lors qu’il nous faut nous identifier ou supporter d’autres méthodes http que les simples GET ou POST.

Au rang des améliorations, il peut aussi être utile de vérifier d’autres statuts HTTP. Je considère ici que toute réponse autre que 200 est une erreur, ce qui n’est pas forcément le cas.

Vous noterez que je manquais d’exemples d’usage dans mon intro… Qu’est-ce que vous téléchargez dans vos applications ?

Il n'y a pas encore de commentaire

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *