213 votes

Télécharger des images avec node.js

J'essaie d'écrire un script pour télécharger des images en utilisant node.js. Voici ce que j'ai jusqu'à présent :

var maxLength = 10 // 10mb
var download = function(uri, callback) {
  http.request(uri)
    .on('response', function(res) {
      if (res.headers['content-length'] > maxLength*1024*1024) {
        callback(new Error('Image too large.'))
      } else if (!~[200, 304].indexOf(res.statusCode)) {
        callback(new Error('Received an invalid status code.'))
      } else if (!res.headers['content-type'].match(/image/)) {
        callback(new Error('Not an image.'))
      } else {
        var body = ''
        res.setEncoding('binary')
        res
          .on('error', function(err) {
            callback(err)
          })
          .on('data', function(chunk) {
            body += chunk
          })
          .on('end', function() {
            // What about Windows?!
            var path = '/tmp/' + Math.random().toString().split('.').pop()
            fs.writeFile(path, body, 'binary', function(err) {
              callback(err, path)
            })
          })
      }
    })
    .on('error', function(err) {
      callback(err)
    })
    .end();
}

Je souhaite toutefois rendre ce système plus robuste :

  1. Y a-t-il des bibliothèques qui font cela et qui le font mieux ?
  2. Y a-t-il une chance que les en-têtes de réponse mentent (sur la longueur, sur le type de contenu) ?
  3. Y a-t-il d'autres codes d'état dont je devrais me préoccuper ? Dois-je me préoccuper des redirections ?
  4. Je crois avoir lu quelque part que binary va être déprécié. Que dois-je faire alors ?
  5. Comment faire pour que cela fonctionne sous Windows ?
  6. Y a-t-il d'autres moyens d'améliorer ce script ?

Pourquoi : pour une fonction similaire à celle d'imgur où les utilisateurs peuvent me donner une URL, je télécharge cette image et je la réaffecte en plusieurs tailles.

456voto

Cezary Wojtkowski Points 731

Je suggère d'utiliser le module de demande . Le téléchargement d'un fichier est aussi simple que le code suivant :

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

var download = function(uri, filename, callback){
  request.head(uri, function(err, res, body){
    console.log('content-type:', res.headers['content-type']);
    console.log('content-length:', res.headers['content-length']);

    request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);
  });
};

download('https://www.google.com/images/srpr/logo3w.png', 'google.png', function(){
  console.log('done');
});

50voto

Nihey Takizawa Points 739

J'ai rencontré ce problème il y a quelques jours, pour une réponse purement NodeJS, je suggérerais d'utiliser Stream pour fusionner les morceaux ensemble.

var http = require('http'),                                                
    Stream = require('stream').Transform,                                  
    fs = require('fs');                                                    

var url = 'http://www.google.com/images/srpr/logo11w.png';                    

http.request(url, function(response) {                                        
  var data = new Stream();                                                    

  response.on('data', function(chunk) {                                       
    data.push(chunk);                                                         
  });                                                                         

  response.on('end', function() {                                             
    fs.writeFileSync('image.png', data.read());                               
  });                                                                         
}).end();

Les versions les plus récentes de Node ne fonctionnent pas bien avec les chaînes binaires, donc la fusion de chunks avec des chaînes n'est pas une bonne idée lorsqu'on travaille avec des données binaires.

*Faites attention lorsque vous utilisez 'data.read()', cela videra le flux pour la prochaine opération 'read()'. Si vous voulez l'utiliser plus d'une fois, stockez-le quelque part.

48voto

Grant Miller Points 6261

Vous pouvez utiliser Axios (a promesse -) pour télécharger des images dans l'ordre de votre choix dans un fichier d'images. environnement asynchrone :

npm i axios

Ensuite, vous pouvez utiliser l'exemple de base suivant pour commencer à télécharger des images :

const fs = require('fs');
const axios = require('axios');

/* ============================================================
  Function: Download Image
============================================================ */

const download_image = (url, image_path) =>
  axios({
    url,
    responseType: 'stream',
  }).then(
    response =>
      new Promise((resolve, reject) => {
        response.data
          .pipe(fs.createWriteStream(image_path))
          .on('finish', () => resolve())
          .on('error', e => reject(e));
      }),
  );

/* ============================================================
  Download Images in Order
============================================================ */

(async () => {
  let example_image_1 = await download_image('https://example.com/test-1.png', 'example-1.png');

  console.log(example_image_1.status); // true
  console.log(example_image_1.error); // ''

  let example_image_2 = await download_image('https://example.com/does-not-exist.png', 'example-2.png');

  console.log(example_image_2.status); // false
  console.log(example_image_2.error); // 'Error: Request failed with status code 404'

  let example_image_3 = await download_image('https://example.com/test-3.png', 'example-3.png');

  console.log(example_image_3.status); // true
  console.log(example_image_3.error); // ''
})();

10voto

fareed namrouti Points 3830

Si vous voulez télécharger des progrès, essayez ceci :

var fs = require('fs');
var request = require('request');
var progress = require('request-progress');

module.exports = function (uri, path, onProgress, onResponse, onError, onEnd) {
    progress(request(uri))
    .on('progress', onProgress)
    .on('response', onResponse)
    .on('error', onError)
    .on('end', onEnd)
    .pipe(fs.createWriteStream(path))
};

comment l'utiliser :

  var download = require('../lib/download');
  download("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png", "~/download/logo.png", function (state) {
            console.log("progress", state);
        }, function (response) {
            console.log("status code", response.statusCode);
        }, function (error) {
            console.log("error", error);
        }, function () {
            console.log("done");
        });

note : vous devez installer les modules request & request-progress en utilisant :

npm install request request-progress --save

10voto

Chandan Chhajer Points 107
var fs = require('fs'),
http = require('http'),
https = require('https');

var Stream = require('stream').Transform;

var downloadImageToUrl = (url, filename, callback) => {

    var client = http;
    if (url.toString().indexOf("https") === 0){
      client = https;
     }

    client.request(url, function(response) {                                        
      var data = new Stream();                                                    

      response.on('data', function(chunk) {                                       
         data.push(chunk);                                                         
      });                                                                         

      response.on('end', function() {                                             
         fs.writeFileSync(filename, data.read());                               
      });                                                                         
   }).end();
};

downloadImageToUrl('https://www.google.com/images/srpr/logo11w.png', 'public/uploads/users/abc.jpg');

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