Cargar imágenes usando Node.js, Express y Mongoose

¡Considere las respuestas más recientes que tienen más información actualizada ya que las cosas han cambiado a lo largo de los años!

Dado que muchas bibliotecas nuevas de Node.js se están volviendo obsoletas rápidamente y de todas maneras hay pocos ejemplos, quiero preguntar sobre la carga de imágenes usando las últimas versiones de Node.js (v0.4.1), Express (1.0.7) y Mongoose ( 1.1.0). ¿Cómo lo han hecho otros?

Encontré: https://github.com/felixge/node-formidable , pero soy nuevo en la carga de imágenes en general, así que quiero aprender cosas generales y formas de hacerlo usando Node.js y Express.

Responderé mi propia pregunta por primera vez. Encontré un ejemplo directamente de la fuente. Por favor, perdona la mala sangría. No estaba seguro de cómo sangrar correctamente al copiar y pegar. El código proviene directamente del ejemplo Express multipart/form-data en 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('
' + '

Image:

' + '

' + '
'); }); 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');

Dado que estás usando express, solo agrega bodyParser:

 app.use(express.bodyParser()); 

entonces su ruta automáticamente tiene acceso a los archivos cargados en los archivos req:

 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 nombra el control de entrada “todo” de esta manera (en Jade):

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

Luego, el archivo cargado está listo para cuando obtenga la ruta y el nombre del archivo original en ‘files.todo’:

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

otras propiedades de req.files útiles:

  • tamaño (en bytes)
  • tipo (por ejemplo, ‘image / png’)
  • lastModifiedate
  • _writeStream.encoding (por ejemplo, ‘binario’)

Puede configurar el middleware del analizador del cuerpo de conexión en un bloque de configuración en su archivo de aplicación principal:

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

Mira, lo mejor que puedes hacer es subir la imagen al disco y guardar la URL en MongoDB. Descanse cuando recupere la imagen nuevamente. Solo especifica la URL y obtendrás una imagen. El código para cargar es el siguiente.

 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; // }); }); }); 

Ahora guarde la ruta de destino en su base de datos MongoDB.

Nuevamente, al recuperar la imagen, solo extraiga la URL de la base de datos MongoDB y úsela en este método.

 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"); } }); 

Prueba este código. Te ayudará.

 app.get('/photos/new', function(req, res){ res.send('
' + '

Data:

' + '

file:

' + '

' + '
'); }); 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); }

También puede usar lo siguiente para establecer una ruta donde guarda el archivo.

 req.form.uploadDir = ""; 

Creé un ejemplo que usa Express y Multer. Es muy simple y evita todas las advertencias de Connect

Podría ayudar a alguien.

De nuevo, si no quiere usar bodyParser, lo siguiente funciona:

 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'); }); 

Para Express 3.0, si desea utilizar los eventos formidables, debe eliminar el middleware multiparte, para que pueda crear la nueva instancia de este.

Para hacer esto:

 app.use(express.bodyParser()); 

Se puede escribir como:

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

Y ahora crea el objeto de formulario:

 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; }; 

También lo publiqué en mi blog Obteniendo form form form en Express 3.0 al cargarlo .

Sé que la pregunta original se refería a versiones específicas, pero también se refería a la “última”: la publicación de @JohnAllen ya no es relevante debido a BodyJeans y a la forma de conexión de Expressjs.

Esto demuestra el fácil de usar bodyParser incorporado ():

  /** * 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('
' + '

Image:

' + '

' + '
'); }); 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');

Esta es una manera de cargar sus imágenes usando el formidable paquete, que se recomienda para bodyParser en versiones posteriores de Express. Esto también incluye la capacidad de cambiar el tamaño de sus imágenes sobre la marcha:

Carga y cambio de tamaño de imágenes (sobre la marcha) con Node.js y Express .

Aquí está la esencia:

 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 = '
'+ ' '+ ' '+ ''+ '
'; res.end(form); }); app.listen(8080);

NOTA: Esto requiere Image Magick para el cambio rápido de tamaño del pulgar.

Hay mi método para cargar archivos múltiples:

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); }) }) } }) 

Asegúrese de que su formulario tenga enctype = "multipart / form-data"

Espero que esto te dé una mano;)