web-dev-qa-db-fra.com

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

Veuillez envisager des réponses plus récentes contenant des informations plus récentes, car les choses ont changé au fil des ans!

Étant donné que beaucoup de nouvelles bibliothèques Node.js sont rapidement rendues obsolètes et qu'il y a relativement peu d'exemples, je voudrais de toute façon poser des questions sur le téléchargement d'images à l'aide de:

  • Node.js (v0.4.1)
  • Express (1.0.7)
  • Mangouste (1.1.0).

Comment les autres l'ont-ils fait?

J'ai trouvé: node-formidable , mais comme je suis novice dans le téléchargement d'images en général, je souhaite donc apprendre des choses générales et des façons de procéder grâce à Node.js et Express.

99
JohnAllen

Je vais répondre à ma propre question pour la première fois. J'ai trouvé un exemple directement de la source. S'il vous plaît pardonnez à la pauvre indentation. Je ne savais pas comment mettre correctement en retrait lors du copier-coller. Le code vient directement de 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');
75
JohnAllen

Puisque vous utilisez Express, ajoutez simplement bodyParser:

app.use(express.bodyParser());

alors votre route 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 appelez 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

Ensuite, le fichier téléchargé est prêt au moment où vous obtenez le chemin et le nom de fichier d'origine dans 'files.todo':

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

autres propriétés req.files utiles:

  • taille (en octets)
  • type (par exemple, 'image/png')
  • lastModified
  • _writeStream.encoding (par exemple, 'binary')
47
Brent Faust

Vous pouvez configurer le middleware d'analyseur de corps de connexion dans un bloc de configuration de votre fichier d'application principal:

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

Vous voyez, la meilleure chose à faire est simplement de télécharger l'image sur le disque et de sauvegarder l'URL dans MongoDB. Reste quand tu récupères l'image à nouveau. Spécifiez simplement l'URL et vous obtiendrez une image. Le code de 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;
            //
        });
    });
});

Enregistrez maintenant le chemin cible dans votre base de données MongoDB.

Là encore, lors de la récupération de l'image, extrayez simplement l'URL de la base de données MongoDB et utilisez-la sur 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");
    }
});
14
Nilesh

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);
}
9
Dar Hamid

Vous pouvez également utiliser ce qui suit pour définir un chemin dans lequel le fichier sera enregistré.

req.form.uploadDir = "<path>";
8
Manuela

J'ai créé un exemple qui utilise Express et Multer. C'est très simple et évite tous les avertissements Connect

Cela pourrait aider quelqu'un.

5
Jon J

Pour Express 3.0, si vous souhaitez utiliser les formidables événements, vous devez supprimer le middleware en plusieurs parties afin de pouvoir en créer la nouvelle instance.

Pour faire ça:

app.use(express.bodyParser());

Peut être écrit comme:

app.use(express.json());
app.use(express.urlencoded());
app.use(express.multipart()); // Remove this line

Et maintenant, créez l'objet formulaire:

exports.upload = function(req, res) {
    var form = new formidable.IncomingForm;
    form.keepExtensions = true;
    form.uploadDir = 'tmp/';

    form.parse(req, function(err, fields, files){
        if (err) return res.end('You found error');
        // Do something with files.image etc
        console.log(files.image);
    });

    form.on('progress', function(bytesReceived, bytesExpected) {
        console.log(bytesReceived + ' ' + bytesExpected);
    });

    form.on('error', function(err) {
        res.writeHead(400, {'content-type': 'text/plain'}); // 400: Bad Request
        res.end('error:\n\n'+util.inspect(err));
    });
    res.end('Done');
    return;
};

J'ai également posté ceci sur mon blog, Obtention d'un objet formulaire formidable dans Express 3.0 lors de l'envoi.

2
Risto Novik

Encore une fois si vous ne voulez pas utiliser bodyParser, les opérations suivantes fonctionnent:

var express = require('express');
var http = require('http');
var app = express();

app.use(express.static('./public'));


app.configure(function(){
    app.use(express.methodOverride());
    app.use(express.multipart({
        uploadDir: './uploads',
        keepExtensions: true
    }));
});


app.use(app.router);

app.get('/upload', function(req, res){
    // Render page with upload form
    res.render('upload');
});

app.post('/upload', function(req, res){
    // Returns json of uploaded file
    res.json(req.files);
});

http.createServer(app).listen(3000, function() {
    console.log('App started');
});
2
Squidinker

Je sais que la question initiale concernait des versions spécifiques, mais elle faisait également référence au "dernier" message - Le message de @JohnAllen n'est plus pertinent en raison de Expressjs bodyParser and connect-form

Ceci démontre la facilité d'utilisation de bodyParser () intégrée:

 /**
 * Module dependencies.
 */

var express = require('express')

var app = express()
app.use(express.bodyParser({ keepExtensions: true, uploadDir: '/home/svn/rest-api/uploaded' }))

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){

    res.send('Uploaded: ' + req.files.image.name)
    return next()

});

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

Voici un moyen de télécharger vos images à l'aide du formidable package, recommandé dans les versions ultérieures d'Express plutôt que sur bodyParser. Cela inclut également la possibilité de redimensionner vos images à la volée:

De mon site Web: Téléchargement et redimensionnement des images (à la volée) avec Node.js et Express .

Voici le Gist:

var express = require("express"),
app = express(),
formidable = require('formidable'),
util = require('util')
fs   = require('fs-extra'),
qt   = require('quickthumb');

// Use quickthumb
app.use(qt.static(__dirname + '/'));

app.post('/upload', function (req, res){
  var form = new formidable.IncomingForm();
  form.parse(req, function(err, fields, files) {
    res.writeHead(200, {'content-type': 'text/plain'});
    res.write('received upload:\n\n');
    res.end(util.inspect({fields: fields, files: files}));
  });

  form.on('end', function(fields, files) {
    /* Temporary location of our uploaded file */
    var temp_path = this.openedFiles[0].path;
    /* The file name of the uploaded file */
    var file_name = this.openedFiles[0].name;
    /* Location where we want to copy the uploaded file */
    var new_location = 'uploads/';

    fs.copy(temp_path, new_location + file_name, function(err) {  
      if (err) {
        console.error(err);
      } else {
        console.log("success!")
      }
    });
  });
});

// Show the upload form 
app.get('/', function (req, res){
  res.writeHead(200, {'Content-Type': 'text/html' });
  /* Display the file upload form. */
  form = '<form action="/upload" enctype="multipart/form-data" method="post">'+ '<input name="title" type="text" />
  '+ '<input multiple="multiple" name="upload" type="file" />
  '+ '<input type="submit" value="Upload" />'+ '</form>';
  res.end(form); 
}); 
app.listen(8080);

REMARQUE: ceci nécessite Image Magick pour le redimensionnement rapide du pouce.

0
Tony Spiro

Voici ma méthode pour télécharger plusieurs fichiers:

Nodejs:

router.post('/upload', function(req , res) {

var multiparty = require('multiparty');
var form = new multiparty.Form();
var fs = require('fs');

form.parse(req, function(err, fields, files) {  
    var imgArray = files.imatges;


    for (var i = 0; i < imgArray.length; i++) {
        var newPath = './public/uploads/'+fields.imgName+'/';
        var singleImg = imgArray[i];
        newPath+= singleImg.originalFilename;
        readAndWriteFile(singleImg, newPath);           
    }
    res.send("File uploaded to: " + newPath);

});

function readAndWriteFile(singleImg, newPath) {

        fs.readFile(singleImg.path , function(err,data) {
            fs.writeFile(newPath,data, function(err) {
                if (err) console.log('ERRRRRR!! :'+err);
                console.log('Fitxer: '+singleImg.originalFilename +' - '+ newPath);
            })
        })
}
})

Assurez-vous que votre formulaire a enctype = "multipart/form-data"

J'espère que cela vous donne un coup de main;)

0
Despertaweb