103 votes

Téléchargement d'images à l'aide de Node.js, Express et Mongoose

Veuillez considérer les réponses plus récentes qui contiennent des informations plus à jour, car les choses ont changé au fil des ans !

Étant donné que de nombreuses nouvelles bibliothèques Node.js sont rapidement rendues obsolètes et qu'il existe de toute façon relativement peu d'exemples, je souhaite poser des questions sur le téléchargement d'images à l'aide des dernières versions de Node.js (v0.4.1), Express (1.0.7) et Mongoose (1.1.0). Comment les autres ont-ils fait ?

J'ai trouvé : https://github.com/felixge/node-formidable Mais je suis novice en matière de téléchargement d'images en général et je veux donc apprendre des trucs généraux et des façons de le faire en utilisant Node.js et Express.

12 votes

Mise à jour Les nouvelles versions d'Express intègrent cette fonctionnalité, pensez-y avant de passer du temps avec 'connect-form'.

4 votes

2015 tl;dr- envoyer des requêtes multipart/form à votre serveur et les analyser avec Multer puisque BodyParser n'analyse plus les fichiers. npm install multer --save et ensuite dans votre application vous pouvez accéder req.files.your_file_param_name et sauvegarder en s3 avec aws-sdk o fs.writeFile(...)

74voto

JohnAllen Points 1522

Je vais répondre à ma propre question pour la première fois. J'ai trouvé un exemple directement à la source. Veuillez pardonner la mauvaise indentation. Je n'étais pas sûr de savoir comment indenter correctement en copiant et collant. Le code provient directement d'Express multipart/form-data exemple sur GitHub.

// Expose modules in ./support for demo purposes
require.paths.unshift(__dirname + '/../../support');

/**
 * Module dependencies.
 */

var express = require('../../lib/express')
  , form = require('connect-form');

var app = express.createServer(
  // connect-form (http://github.com/visionmedia/connect-form)
  // middleware uses the formidable middleware to parse urlencoded
  // and multipart form data
  form({ keepExtensions: true })
);

app.get('/', function(req, res){
  res.send('<form method="post" enctype="multipart/form-data">'
    + '<p>Image: <input type="file" name="image" /></p>'
    + '<p><input type="submit" value="Upload" /></p>'
    + '</form>');
});

app.post('/', function(req, res, next){

  // connect-form adds the req.form object
  // we can (optionally) define onComplete, passing
  // the exception (if any) fields parsed, and files parsed
  req.form.complete(function(err, fields, files){
    if (err) {
      next(err);
    } else {
      console.log('\nuploaded %s to %s'
        ,  files.image.filename
        , files.image.path);
      res.redirect('back');
    }
  });

  // We can add listeners for several form
  // events such as "progress"
  req.form.on('progress', function(bytesReceived, bytesExpected){
    var percent = (bytesReceived / bytesExpected * 100) | 0;
    process.stdout.write('Uploading: %' + percent + '\r');
  });
});

app.listen(3000);
console.log('Express app started on port 3000');

3 votes

Oui, mais comment sauvegarder le fichier ?

1 votes

@NickRetallack le fichier enregistré est stocké dans files.image.path

0 votes

@robin-duckett, comment spécifiez-vous le nom du fichier et le chemin d'accès au préalable ?

46voto

Brent Foust Points 1786

Puisque vous utilisez express, ajoutez simplement bodyParser :

app.use(express.bodyParser());

alors votre itinéraire a automatiquement accès au(x) fichier(s) téléchargé(s) dans req.files :

app.post('/todo/create', function (req, res) {
    // TODO: move and rename the file using req.files.path & .name)
    res.send(console.dir(req.files));  // DEBUG: display available fields
});

Si vous nommez le contrôle d'entrée "todo" comme ceci (en Jade) :

form(action="/todo/create", method="POST", enctype="multipart/form-data")
    input(type='file', name='todo')
    button(type='submit') New

Le fichier téléchargé est alors prêt au moment où vous obtenez le chemin d'accès et le nom du fichier original dans 'files.todo' :

  • req.files.todo.path, et
  • req.files.todo.name

d'autres propriétés req.files utiles :

  • taille (en octets)
  • type (par exemple, "image/png")
  • lastModifiedate
  • _writeStream.encoding (par exemple, 'binary')

0 votes

Je n'ai jamais entendu parler de ça de cette façon et je vais aller de l'avant et dire que ces gars-là sont les meilleurs. developer.mozilla.org/en-US/docs/JavaScript/Guide/ donc je suppose que nous avons tous les deux tort ;)

0 votes

bodyParser n'est pas sûr, du moins d'après ceci : andrewkelley.me/post/do-not-use-bodyparser-with-express-js.html . La réponse de Jon J a fonctionné pour moi.

0 votes

Par "non sécurisé", on entend simplement que des fichiers temporaires sont créés, de sorte qu'une "attaque" pourrait éventuellement remplir l'espace disque du serveur avec des fichiers temporaires. Il s'agit plutôt d'un problème de robustesse, et non d'une faille de sécurité.

19voto

jibsales Points 3766

Vous pouvez configurer l'intergiciel connect body parserware dans un bloc de configuration du fichier principal de votre application :

    /** Form Handling */
    app.use(express.bodyParser({
        uploadDir: '/tmp/uploads',
        keepExtensions: true
    }))
    app.use(express.limit('5mb'));

0 votes

C'est en fait la meilleure façon de gérer les téléchargements, je suppose. Gardez le fichier si vous le souhaitez, sinon supprimez-le simplement au lieu de le copier à un autre endroit. Merci.

2 votes

@AksharPrabhuDesai Oui et non. Disons que vous avez un outil de téléchargement/coupe de photos. Si vous autorisez l'utilisateur à télécharger directement dans votre dossier public, vous présentez une grave faille de sécurité. Dans ce cas, il est préférable de télécharger dans un dossier tmp, puis de le transférer dans votre dossier public après avoir vérifié que le fichier n'est pas un cheval de Troie.

0 votes

Il ne semble plus être supporté. Cela semblait être une bonne solution.

14voto

Nilesh Points 436

Vous voyez, la meilleure chose à faire est de simplement télécharger l'image sur le disque et de sauvegarder l'URL dans MongoDB. Reposez-vous quand vous récupérez l'image à nouveau. Il suffit de spécifier l'URL, et vous obtiendrez une image. Le code pour le téléchargement est le suivant.

app.post('/upload', function(req, res) {
    // Get the temporary location of the file
    var tmp_path = req.files.thumbnail.path;
    // Set where the file should actually exists - in this case it is in the "images" directory.
    target_path = '/tmp/' + req.files.thumbnail.name;
    // Move the file from the temporary location to the intended location
    fs.rename(tmp_path, target_path, function(err) {
        if (err)
            throw err;
        // Delete the temporary file, so that the explicitly set temporary upload dir does not get filled with unwanted files.
        fs.unlink(tmp_path, function() {
            if (err)
                throw err;
            //
        });
    });
});

Maintenant, enregistrez le chemin cible dans votre base de données MongoDB.

Encore une fois, lors de la récupération de l'image, il suffit d'extraire l'URL de la base de données MongoDB, et de l'utiliser dans cette méthode.

fs.readFile(target_path, "binary", function(error, file) {
    if(error) {
        res.writeHead(500, {"Content-Type": "text/plain"});
        res.write(error + "\n");
        res.end();
    }
    else {
        res.writeHead(200, {"Content-Type": "image/png"});
        res.write(file, "binary");
    }
});

9voto

Dar Hamid Points 595

Essayez ce code. Il vous aidera.

app.get('/photos/new', function(req, res){
  res.send('<form method="post" enctype="multipart/form-data">'
    + '<p>Data: <input type="filename" name="filename" /></p>'
    + '<p>file: <input type="file" name="file" /></p>'
    + '<p><input type="submit" value="Upload" /></p>'
    + '</form>');
});

 app.post('/photos/new', function(req, res) {
  req.form.complete(function(err, fields, files) {
    if(err) {
      next(err);
    } else {
      ins = fs.createReadStream(files.photo.path);
      ous = fs.createWriteStream(__dirname + '/directory were u want to store image/' + files.photo.filename);
      util.pump(ins, ous, function(err) {
        if(err) {
          next(err);
        } else {
          res.redirect('/photos');
        }
      });
      //console.log('\nUploaded %s to %s', files.photo.filename, files.photo.path);
      //res.send('Uploaded ' + files.photo.filename + ' to ' + files.photo.path);
    }
  });
});

if (!module.parent) {
  app.listen(8000);
  console.log("Express server listening on port %d, log on to http://127.0.0.1:8000", app.address().port);
}

0 votes

util.pump(ins, ous) est déprécié, cela pourrait être fait avec ins.pipe(ous); maintenant. Mais cela supprimera-t-il le fichier image sur l'ancien emplacement ?

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