620 votes

Comment télécharger un fichier avec Node.js (sans utiliser de bibliothèques tierces) ?

Comment télécharger un fichier avec Node.js ? sans utiliser de bibliothèques tierces ?

Je n'ai pas besoin de quelque chose de spécial. Je veux seulement télécharger un fichier à partir d'une URL donnée, puis l'enregistrer dans un répertoire donné.

6 votes

"télécharger un fichier avec node.js" - voulez-vous dire télécharger au serveur ? ou récupérer un fichier d'un serveur distant en utilisant votre serveur ? ou servir un fichier à un client pour le télécharger à partir de votre serveur node.js ?

123 votes

"Je veux seulement télécharger un fichier à partir d'une url donnée, puis l'enregistrer dans un répertoire donné", cela semble assez clair. :)

55 votes

Joseph affirme à tort que tous les processus de nœuds sont des processus de serveurs.

838voto

Brandon Tilley Points 49142

Vous pouvez créer une interface HTTP GET et pipe son response dans un flux de fichiers inscriptibles :

const http = require('http'); // or 'https' for https:// URLs
const fs = require('fs');

const file = fs.createWriteStream("file.jpg");
const request = http.get("http://i3.ytimg.com/vi/J---aiyznGQ/mqdefault.jpg", function(response) {
  response.pipe(file);
});

Si vous souhaitez prendre en charge la collecte d'informations sur la ligne de commande - comme la spécification d'un fichier ou d'un répertoire cible, ou d'une URL - consultez quelque chose comme Commandant .

4 votes

J'ai obtenu la sortie console suivante lorsque j'ai exécuté ce script : node.js:201 throw e; // process.nextTick error, or 'error' event on first tick ^ Error: connect ECONNREFUSED at errnoException (net.js:646:11) at Object.afterConnect [as oncomplete] (net.js:637:18) .

0 votes

Essayez d'utiliser une autre URL sur le http.get ligne ; peut-être http://i3.ytimg.com/vi/J---aiyznGQ/mqdefault.jpg (et remplacer file.png con file.jpg ).

0 votes

Pourquoi cette erreur se produirait-elle en premier lieu ? L'image est toujours en ligne ( im.glogster.com/media/2/5/24/10/5241033.png ), alors pourquoi cela produit-il une erreur ? Je ne comprends toujours pas.

577voto

Vince Yuan Points 1735

N'oubliez pas de gérer les erreurs ! Le code suivant est basé sur la réponse d'Augusto Roman.

var http = require('http');
var fs = require('fs');

var download = function(url, dest, cb) {
  var file = fs.createWriteStream(dest);
  var request = http.get(url, function(response) {
    response.pipe(file);
    file.on('finish', function() {
      file.close(cb);  // close() is async, call cb after close completes.
    });
  }).on('error', function(err) { // Handle errors
    fs.unlink(dest); // Delete the file async. (But we don't check the result)
    if (cb) cb(err.message);
  });
};

2 votes

@vince-yuan est download() lui-même pipe capable ?

0 votes

@theGrayFox Parce que le code dans cette réponse est beaucoup plus long que celui accepté :)

4 votes

@VinceYuan le callback m'embrouille. si j'invoque maintenant download() comment je m'y prendrais ? Qu'est-ce que je placerais comme cb argument ? J'ai le download('someURI', '/some/destination', cb) mais ne comprend pas ce qu'il faut mettre dans le cb

177voto

gfxmonk Points 2981

Comme l'a dit Michelle Tilley, mais avec le flux de contrôle approprié :

var http = require('http');
var fs = require('fs');

var download = function(url, dest, cb) {
  var file = fs.createWriteStream(dest);
  http.get(url, function(response) {
    response.pipe(file);
    file.on('finish', function() {
      file.close(cb);
    });
  });
}

Sans attendre le finish les scripts naïfs peuvent se retrouver avec un fichier incomplet.

Edit : Merci à @Augusto Roman d'avoir signalé que cb doit être transmis à file.close qui n'est pas appelé explicitement.

7 votes

Le rappel me perturbe. si j'invoque maintenant download() Comment dois-je m'y prendre ? Qu'est-ce que je placerais comme cb argument ? J'ai le download('someURI', '/some/destination', cb) mais ne comprend pas ce qu'il faut mettre dans le cb

3 votes

@Abdul Vous spécifiez le callback avec une fonction seulement si vous avez besoin de faire quelque chose lorsque le fichier a été récupéré avec succès.

0 votes

Il serait bon de vérifier le code d'état avant de sauvegarder : response.statusCode == 200

51voto

Augusto Roman Points 111

La réponse de gfxmonk a une course aux données très serrée entre le callback et l'objet file.close() à compléter. file.close() prend en fait un callback qui est appelé lorsque la fermeture est terminée. Sinon, les utilisations immédiates du fichier peuvent échouer (très rarement !).

Une solution complète est :

var http = require('http');
var fs = require('fs');

var download = function(url, dest, cb) {
  var file = fs.createWriteStream(dest);
  var request = http.get(url, function(response) {
    response.pipe(file);
    file.on('finish', function() {
      file.close(cb);  // close() is async, call cb after close completes.
    });
  });
}

Sans attendre l'événement de fin, les scripts naïfs peuvent se retrouver avec un fichier incomplet. Sans programmer l'événement cb via close, vous risquez d'obtenir une course entre l'accès au fichier et le fait que le fichier soit réellement prêt.

2 votes

Pour quelle raison stockez-vous la demande dans une variable ?

0 votes

Il la "stocke" dans une variable afin qu'elle ne devienne pas une variable globale par défaut.

0 votes

@philk comment savez-vous qu'une variable globale est créée si var request = est supprimée ?

17voto

Hors Sujet Points 1528

Solution avec timeout, pour éviter les fuites de mémoire :

Le code suivant est basé sur la réponse de Brandon Tilley :

var http = require('http'),
    fs = require('fs');

var request = http.get("http://example12345.com/yourfile.html", function(response) {
    if (response.statusCode === 200) {
        var file = fs.createWriteStream("copy.html");
        response.pipe(file);
    }
    // Add timeout.
    request.setTimeout(12000, function () {
        request.abort();
    });
});

Ne faites pas de fichier lorsque vous obtenez une erreur, et préférez utiliser le timeout pour fermer votre requête après X secondes.

1 votes

Ce n'est qu'un fichier, il n'a pas de protocole ou de serveur à télécharger... http.get("http://example.com/yourfile.html",function(){})

0 votes

Y a-t-il une fuite de mémoire dans cette réponse : stackoverflow.com/a/22793628/242933 ?

0 votes

Vous pouvez ajouter un délai d'attente comme je l'ai fait dans http.get . La fuite de mémoire ne se produit que si le fichier prend trop de temps à être téléchargé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X