65 votes

Écriture d'image sur un serveur local

Mise à jour

La réponse acceptée était bonne l'année dernière mais aujourd'hui j'utiliserais le package que tout le monde utilise : https://github.com/mikeal/request


Original

Je tente de récupérer le logo de google et de l'enregistrer sur mon serveur avec node.js.

Voici ce que j'ai pour le moment et qui ne fonctionne pas :

        var options = {
            host: 'google.com',
            port: 80,
            path: '/images/logos/ps_logo2.png'
        };

        var request = http.get(options);

        request.on('response', function (res) {
            res.on('data', function (chunk) {
                fs.writeFile(dir+'image.png', chunk, function (err) {
                    if (err) throw err;
                    console.log('C'est enregistré !');
                });
            });
        });

Comment puis-je faire fonctionner cela ?

93voto

Ricardo Tomasi Points 13398

Quelques choses se passent ici :

  1. Je suppose que vous avez besoin de fs/http, et avez défini la variable dir :)
  2. google.com redirige vers www.google.com, donc vous sauvegardez le corps de la réponse de la redirection, pas l'image
  3. la réponse est en streaming. Cela signifie que l'événement 'data' se déclenche plusieurs fois, pas une seule. Vous devez sauvegarder et joindre tous les morceaux ensemble pour obtenir le corps de la réponse complet
  4. puisque vous obtenez des données binaires, vous devez définir l'encodage correctement sur la réponse et writeFile (par défaut c'est utf8)

Cela devrait fonctionner :

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

options = {
    host: 'www.google.com'
  , port: 80
  , path: '/images/logos/ps_logo2.png'
}

var request = http.get(options, function(res){
    var imagedata = ''
    res.setEncoding('binary')

    res.on('data', function(chunk){
        imagedata += chunk
    })

    res.on('end', function(){
        fs.writeFile('logo.png', imagedata, 'binary', function(err){
            if (err) throw err
            console.log('Fichier enregistré.')
        })
    })

})

15 votes

Comment se fait-il que vous n'utilisiez pas de point-virgules ?

3 votes

7 votes

Ceci est un conseil terrible. Ne jamais .setEncoding('binary') et utiliser res.pipe(fs.createWriteStream()) au lieu de mettre l'image entière en mémoire tampon. Vous pouvez utiliser cette bibliothèque si vous êtes trop paresseux : github.com/stream-utils/save-to

40voto

foohey Points 727

Ce fil est ancien mais je voulais faire la même chose avec le package https://github.com/mikeal/request.

Voici un exemple de travail

var fs = require('fs');
var request = require('request');
// Ou avec des cookies
// var request = require('request').defaults({jar: true});

request.get({url: 'https://someurl/somefile.torrent', encoding: 'binary'}, function (err, response, body) {
  fs.writeFile("/tmp/test.torrent", body, 'binary', function(err) {
    if(err)
      console.log(err);
    else
      console.log("Le fichier a été enregistré !");
  }); 
});

5 votes

Les documents indiquent maintenant de définir l'encodage sur null pour binaire sinon il est considéré comme utf8 : github.com/request/request "encodage - Encodage à utiliser sur setEncoding des données de réponse. Si null, le corps est renvoyé en tant que Buffer. Tout ce qui n'est pas null (y compris la valeur par défaut de undefined) sera transmis en tant que paramètre d'encodage à toString() (ce qui signifie que cela est effectivement utf8 par défaut). (Remarque : si vous prévoyez des données binaires, vous devez définir l'encodage sur null.)"

0 votes

Je confirme, vous devriez maintenant définir { encoding: null }

27voto

Drasill Points 1900

Je vous suggère d'utiliser http-request, afin que même les redirections soient gérées.

var http = require('http-request');
var options = {url: 'http://localhost/foo.pdf'};
http.get(options, '/path/to/foo.pdf', function (error, result) {
    if (error) {
        console.error(error);
    } else {
        console.log('Fichier téléchargé à l'emplacement : ' + result.file);
    }
});

2 votes

Doit admettre, c'est aussi simple qu'un téléchargement http peut l'être.

0 votes

Apparemment, http-get a atteint la fin de sa vie, et son successeur est http-request.

0 votes

En effet, et il semble totalement rétro-compatible.

6voto

yuqin Points 51

Que diriez-vous de cela?

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

options = {
    host: 'www.google.com' , 
    port: 80,
    path: '/images/logos/ps_logo2.png'
}

var request = http.get(options, function(res){

//var imagedata = ''
//res.setEncoding('binary')

var chunks = [];

res.on('data', function(chunk){

    //imagedata += chunk
    chunks.push(chunk)

})

res.on('end', function(){

    //fs.writeFile('logo.png', imagedata, 'binary', function(err){

    var buffer = Buffer.concat(chunks)
    fs.writeFile('logo.png', buffer, function(err){
        if (err) throw err
        console.log('Fichier enregistré.')
    })

})

0 votes

Que se passe-t-il si l'URL est incorrecte? J'étais en train de sauvegarder Erreur 404 (non trouvée)!!1 </x-turndown>

0 votes

@yuquin, Comment utiliser le code pour enregistrer cette image eteacher.png

3voto

BlackBeard Points 4608

Manière la plus propre de sauvegarder une image localement en utilisant request:

const request = require('request');
request('http://lien/vers/votre/image/fichier.png').pipe(fs.createWriteStream('nomFichier.png'))

Si vous avez besoin d'ajouter un jeton d'authentification dans les en-têtes, faites ceci:

const request = require('request');
request({
        url: 'http://lien/vers/votre/image/fichier.png',
        headers: {
            "X-Token-Auth": TOKEN,
        }
    }).pipe(fs.createWriteStream('nomFichier.png'))

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