用于使用node.js编写用于图像上传的filter列表的devise模式

我在node.js中写了一个简单的图片上传器,并且expression了4.当文件发布时,封闭的图片将通过一系列filter运行:

  • 这是一个可接受的MIMEtypes? (jpg,gif,png,tiff)
  • 这是否有相应的可以接受的延伸?
  • 这个图像是不是2兆字节?
  • 该文件被上传截断了吗?

我习惯于在同步语言中做这种事情,我会通过一系列if来运行对象,如果有什么事情会返回false。 然而,在JavaScript中,相同的方法将导致发送多个头。

我通过在其他子句中嵌套filter来解决这个问题,但这很快变得非常笨拙。 这似乎是一个常见的devise模式,那么处理这样的事情的最好办法是什么?

app.js:

var express = require('express') , fs = require('fs') , bodyParser = require('body-parser') , serveStatic = require('serve-static') , multer = require('multer') , port = 80 ; var app = express(); app.set('views', __dirname + '/views'); app.set('view engine', 'jade'); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(multer({ dest: "./images/tmp" })) app.use(serveStatic(__dirname + '/public')); app.listen(port); app.get('/', function(req, res, next) { console.log(req); res.render("uploader"); }); var uploadConfig = { acceptedMimeTypes : [ "image/jpeg", "image/png", "image/gif", "image/tiff" ], acceptedExtensions : [ "jpg", "jpeg", "png", "gif", "tiff" ], maxFileSize : 2000000 }; app.post('/upload', function(req, res, next) { var image = req.files.image; var removeTempImage = function() { fs.unlink('images/tmp/' + image.name) }; // Here is where things become a mess if (uploadConfig.acceptedMimeTypes.indexOf(image.mimetype) == -1) { removeTempImage(); res.send({success: false, message: "Incorrect MIME type"}); } else { if (uploadConfig.acceptedExtensions.indexOf(image.extension) == -1) { removeTempImage(); res.send({success: false, message: "Incorrect file extension"}); } else { if (image.size > uploadConfig.maxFileSize) { removeTempImage(); res.send({success: false, message: "File is too large"}); } else { if (image.truncated) { removeTempImage(); res.send({success: false, message: "The file was truncated"}); } else { // it survived the gauntlet fs.rename('images/tmp/' + image.name, 'public/completeImgs/' + image.name, function (err) { if (err) { removeTempImage; res.send({success: false, message: err}); } else { res.send({success: true, message: "Your image has been saved"}); } }) } } } } }); console.log("uploader is listening on port " + port); 

uploader.jade

 doctype html head body h1 Image Uploader form(method="post" action="/upload" enctype="multipart/form-data") input(type="file" name="image") input(type="submit") h1 !{test} 

您可以使用BlueBird等Promise库:

 Promise.resolve(image) .then(function(image) { if (uploadConfig.acceptedMimeTypes.indexOf(image.mimetype) == -1) { throw "Incorrect MIME type"; } return image; }) .then(function(image) { if (image.size > uploadConfig.maxFileSize) { throw "File is too large"; } return image; }) .then(function(image) { if (image.truncated) { throw "The file was truncated"; } return image; }) .then(function(image) { return fs.renameAsync('images/tmp/' + image.name, 'public/completeImgs/' + image.name) }) .then(function(err) { if (err) throw err; }) .then(function() { res.send({success: true, message: "Your image has been saved"}); }) .catch(function(err) { removeTempImage(); res.send({success: false, message: err}); }); 

那么,所有的检查都是同步的。 只需要像这样的东西:

 app.post('/upload', function (req, res, next) { var image = req.files.image; var removeTempImage = function () { fs.unlink('images/tmp/' + image.name) }; // Here is where things become a mess if (uploadConfig.acceptedMimeTypes.indexOf(image.mimetype) == -1) { removeTempImage(); res.send({ success: false, message: "Incorrect MIME type" }); return; } if (uploadConfig.acceptedExtensions.indexOf(image.extension) == -1) { removeTempImage(); res.send({ success: false, message: "Incorrect file extension" }); return; } if (image.size > uploadConfig.maxFileSize) { removeTempImage(); res.send({ success: false, message: "File is too large" }); return; } if (image.truncated) { removeTempImage(); res.send({ success: false, message: "The file was truncated" }); return; } // it survived the gauntlet fs.rename('images/tmp/' + image.name, 'public/completeImgs/' + image.name, function (err) { if (err) { removeTempImage; res.send({ success: false, message: err }); } else { res.send({ success: true, message: "Your image has been saved" }); } }); }); 

此外,大部分节点OOTBasynchronousfunction也可用作同步版本 。

我自己也没有使用过,但是如果你看一下这个多function页面,它有很多选项,其中一个可以让你至less消除尺寸检查。 https://www.npmjs.com/package/multer 。 此外,您不必在此处执行任何asynchronous操作。 当你的post函数被调用的时候,多function对象已经被填写了,文件正在等待你。

但是这样的事情呢?

 var error_messages = ''; if (uploadConfig.acceptedMimeTypes.indexOf(image.mimetype) == -1) { error_messages = "Incorrect MIME type "; } if (uploadConfig.acceptedExtensions.indexOf(image.extension) == -1) { error_messages += "Incorrect file extension "; } if (image.size > uploadConfig.maxFileSize) { error_messages += "File is too large "); } if (image.truncated) { error_messages += "The file was truncated "; } if(error_messages === ''){ fs.rename('images/tmp/' + image.name, 'public/completeImgs/' + image.name, function (err) { if (err) { removeTempImage; res.send({success: false, message: err}); } else { res.send({success: true, message: "Your image has been saved"}); } }); } else { res.send({success: false, message: error_messages}); } 

不可否认的是,像这样连接错误信息是很麻烦的。 你可以把它们放在一个数组中,并将数组传递给视图或其他东西。