用于编写用于使用 node.js 上传图像的筛选器列表的设计模式

Design pattern for writing a list of filters for image uploading using node.js

本文关键字:用于 筛选 图像 设计模式 列表 node js      更新时间:2023-09-26

我在node中编写一个简单的图像上传器.js并表达4。 发布文件时,随附的图像将通过一系列过滤器运行:

  • 这是可接受的 MIME 类型吗?(JPG, GIF, PNG, TIFF)
  • 这是否有相应的可接受的扩展?
  • 此图像是否小于 2 MB?
  • 文件在上传过程中是否已被截断?

我习惯于在同步语言中做这种事情,我会通过一系列 if 运行对象,如果捕获某些内容,则返回 false。 然而,在javascript中,相同的方法将导致发送多个标头。

我已经通过在 else 子句中嵌套过滤器来解决这个问题,但这很快就会变得非常笨拙。 这似乎是一种常见的设计模式,那么处理这样的事情的最佳方法是什么?

应用.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);

上传者.翡翠

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}

好吧,你所有的检查都是同步的。就这样吧:

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 异步功能也可作为同步版本使用。

你可以使用像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});
    });

我自己还没有使用过 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});
}

诚然,像这样连接错误消息是很糟糕的。 你可以把它们放在一个数组中,然后将数组传递给视图或其他东西。