使用Node.js,Express和Mongoose上传图像

请考虑更新的答案,因为这些年来事情已经发生了变化,所以有更多的最新信息!

由于很多新的Node.js库很快就被废弃了,而且还有相对较less的例子,所以我想问一下使用最新版本的Node.js(v0.4.1),Express(1.0.7)和Mongoose 1.1.0)。 别人怎么做到的?

我发现: https : //github.com/felixge/node-formidable ,但我是一般上传图片的新手,所以我想通过Node.js和Express学习一些常用的东西和方法。

我会第一次回答我自己的问题。 我从源头上find了一个例子。 请原谅可怜的缩进。 我不确定复制和粘贴时如何正确缩进。 代码直接来自GitHub上的Express multipart/form-data示例 。

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

由于您使用快递,只需添加bodyParser:

 app.use(express.bodyParser()); 

那么您的路线将自动访问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 }); 

如果你把这个input控件命名为“todo”(在Jade中):

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

然后,在'files.todo'中获得path和原始文件名时,上传的文件就准备好了:

  • req.files.todo.path和
  • req.files.todo.name

其他有用的req.files属性:

  • 大小(以字节为单位)
  • 键入(例如'image / png')
  • lastModifiedate
  • _writeStream.encoding(例如,“二进制”)

您可以在主应用程序文件的configuration块中configuration连接主体parsing器中间件:

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

看,你可以做的最好的事情就是上传图像到磁盘并保存在MongoDB的URL。 rest时再次检索图像。 只需指定url,即可获得图片。 上传代码如下。

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

现在将目标path保存在MongoDB数据库中。

同样,在检索图像时,只需从MongoDB数据库中提取URL,然后在此方法上使用它。

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

试试这个代码,它会有帮助。

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

您还可以使用以下设置保存文件的path。

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

我创build了一个使用Express和Multer的例子。 这是非常简单的,并避免所有的连接警告

这可能有助于某人。

同样,如果你不想使用bodyParser,下面的工作:

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

对于Express 3.0,如果要使用强大的事件,则必须删除多部分中间件,以便可以创build它的新实例。

去做这个:

 app.use(express.bodyParser()); 

可以写成:

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

现在创build表单对象:

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

我也在我的博客上发布了这个, 在Express 3.0上获得强大的表单对象

我知道原来的问题涉及到具体的版本,但也提到了“最新” – @JohnAllen的post已经不再相关,因为Expressjs bodyParser和connect-form

这演示了易于使用的内置bodyParser():

  /** * 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'); 

这里有一种方法可以使用强大的软件包来上传你的图片,而在更高版本的Express中,推荐使用bodyParser。 这还包括在运行中调整图像大小的function:

使用Node.js和Express来上传和调整图像大小(即时) 。

要点是:

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

注:这需要图像Magick快速拇指大小调整。

有我的方法来多个上传文件:

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

确保你的表单有enctype =“multipart / form-data”

我希望这给你一个手;)