使用 node.js 编写图像上传过滤器列表的设计模式
Design pattern for writing a list of filters for image uploading using node.js
我正在node.js写一个简单的图片上传器并表达4。当文件被发布时,附上的图片会运行通过一系列的过滤器:
- 这是可接受的 MIME 类型吗? (jpg, gif, png, tiff)
- 这是否有相应的可接受的扩展名?
- 这张图片小于 2 兆字节吗?
- 上传的文件是否已被分类运行?
我习惯在同步语言中做这种事情,我会 运行 通过一系列 if 的 object ,如果捕获到 return false 。然而,在 javascript 中,相同的方法将导致发送多个 headers.
我已经通过在 else 子句中嵌套过滤器来解决这个问题,但这很快就会变得非常笨拙。这似乎是一种常见的设计模式,那么处理此类问题的最佳方法是什么?
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}
您可以使用 Promise 库,例如 BlueBird:
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});
});
我自己还没有使用过 multer,但是如果您查看 multer 页面,它有很多选项,其中之一至少可以让您消除尺寸检查。 https://www.npmjs.com/package/multer。此外,您不必在此处执行任何异步操作。当您的 post 函数被调用时,multer 对象已经填写完毕,文件正在等待您。
但是像这样的事情呢:
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});
}
无可否认,像那样连接错误消息是胡说八道。您可以将它们放在一个数组中并将该数组传递给视图或其他东西。
嗯,你所有的支票都是同步的。就这样吧:
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" });
}
});
});
此外,大多数节点 OOTB 异步功能 also available as sync versions。
我正在node.js写一个简单的图片上传器并表达4。当文件被发布时,附上的图片会运行通过一系列的过滤器:
- 这是可接受的 MIME 类型吗? (jpg, gif, png, tiff)
- 这是否有相应的可接受的扩展名?
- 这张图片小于 2 兆字节吗?
- 上传的文件是否已被分类运行?
我习惯在同步语言中做这种事情,我会 运行 通过一系列 if 的 object ,如果捕获到 return false 。然而,在 javascript 中,相同的方法将导致发送多个 headers.
我已经通过在 else 子句中嵌套过滤器来解决这个问题,但这很快就会变得非常笨拙。这似乎是一种常见的设计模式,那么处理此类问题的最佳方法是什么?
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}
您可以使用 Promise 库,例如 BlueBird:
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});
});
我自己还没有使用过 multer,但是如果您查看 multer 页面,它有很多选项,其中之一至少可以让您消除尺寸检查。 https://www.npmjs.com/package/multer。此外,您不必在此处执行任何异步操作。当您的 post 函数被调用时,multer 对象已经填写完毕,文件正在等待您。
但是像这样的事情呢:
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});
}
无可否认,像那样连接错误消息是胡说八道。您可以将它们放在一个数组中并将该数组传递给视图或其他东西。
嗯,你所有的支票都是同步的。就这样吧:
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" });
}
});
});
此外,大多数节点 OOTB 异步功能 also available as sync versions。