解析多部分表单数据,然后使用 Multer(Node 模块)上传文件
Parse multipart form data and then upload a file with Multer (Node module)
我在尝试弄清楚如何防止 Multer 在已将条目添加到数据库的情况下上传文件时遇到了一些麻烦。
在我的场景中,我有一个多部分表单,您可以在其中添加指定 ID 的啤酒。它有 2 个输入,一个带有文本输入 (id),另一个带有文件输入 (beerImage)。
我想做的是,在上传文件之前,检查它是否已存在于数据库中,如果不存在,则上传文件。目前,我的代码是先上传文件,然后检查它是否存在,这是一件坏事!
这是我的代码:
var express = require('express');
var router = express.Router();
var multer = require('multer');
var database = require('../services/database');
var upload = multer({ dest: 'uploads/' });
var cpUpload = upload.fields([{ name: 'beerImage', maxCount: 1 } ]);
router.route('/beers')
.post(function (req, res, next) {
// I'd like to use req.body.id in the query here, but it doesn't exist yet!
cpUpload(req, res, function (err) {
if (err) {
return next(new Error('Error uploading file: ' + err.message + ' (' + err.field + ')'));
} else {
database.getConnection().done(function (conn) {
conn.query('SELECT COUNT(*) AS beersCount FROM beers WHERE id=?', req.body.id, function (err, rows, fields) {
if (err) {
conn.release();
return next(err);
}
if (rows[0].beersCount > 0) {
conn.release();
return next(new Error('Beer "' + req.body.id + '" already exists!'));
} else {
delete req.body.beerImage;
conn.query('INSERT INTO beers SET ?', req.body, function (err, rows, fields) {
conn.release();
if (err) {
return next(err);
}
res.json({ message: 'Beer "' + req.body.id + '" added!' });
});
}
});
});
}
});
});
module.exports = router;
我找不到先 "parse" 多部分表单数据的方法(以便能够使用 req.body.id 进行查询并检查它是否存在),然后再决定是否要是否上传文件。似乎 "cpUpload" 同时做这两件事!
知道如何先获取 "req.body.id"(进行查询)然后决定是否要上传文件吗?
您必须先上传文件,然后再测试它是否存在。然后保存或删除它
我发现 Multer 上有一个名为 "fileFilter" 的功能,您可以在其中控制接受哪些文件。在这里,我已经能够执行所需的查询以检查该条目是否存在。
- 这就是我在上传到云之前实现
multipart/formdata
文件字段和文本字段验证的方法。我在 multer
中的 filterFile
函数如下所示:
- 注意使用邮递员的表单数据发送的任何数据都被视为
multipart/formdata
。您必须使用 multer 或其他类似的库才能解析表单数据。
- 对于
x-www-form-urlencoded
和raw
来自postman的数据不需要multer来解析。您可以使用 body-parser
或 express 内置中间件 express.json()
和 express.urlencoded({ extended: false, })
解析这些数据
filterFile = async (req, file, cb) => {
// if mimetypes are expected mimetypes
const allowedMimeTypes = ["image/jpeg", "image/jpg", "image/png"];
if (allowedMimeTypes.includes(file.mimetype)) {
// then validate formdata fields
// reject the request with error if any validation fails
try {
let { highlights, specifications, ...rest } = req.body;
// deserializing string into respective javascript object(here into an array datatype) to facilate validation
highlights = JSON.parse(req.body.highlights);
specifications = JSON.parse(req.body.specifications);
// constructing deserialized formdata
const formdata = { highlights, specifications, ...rest };
// using Joi for validation
let skuAndProductResult = await skuAndProductSchema.validateAsync(
formdata
);
if (skuAndProductResult) {
// accept the fields and proceed to the next middleware
cb(null, true);
return;
}
// reject the request with error
cb(true, false);
return;
} catch (err) {
// reject the request with error
cb(err, false);
}
} else {
// To reject this file pass `false`
cb(`${file.mimetype} is not supported`, false);
}
};
我在尝试弄清楚如何防止 Multer 在已将条目添加到数据库的情况下上传文件时遇到了一些麻烦。
在我的场景中,我有一个多部分表单,您可以在其中添加指定 ID 的啤酒。它有 2 个输入,一个带有文本输入 (id),另一个带有文件输入 (beerImage)。
我想做的是,在上传文件之前,检查它是否已存在于数据库中,如果不存在,则上传文件。目前,我的代码是先上传文件,然后检查它是否存在,这是一件坏事!
这是我的代码:
var express = require('express');
var router = express.Router();
var multer = require('multer');
var database = require('../services/database');
var upload = multer({ dest: 'uploads/' });
var cpUpload = upload.fields([{ name: 'beerImage', maxCount: 1 } ]);
router.route('/beers')
.post(function (req, res, next) {
// I'd like to use req.body.id in the query here, but it doesn't exist yet!
cpUpload(req, res, function (err) {
if (err) {
return next(new Error('Error uploading file: ' + err.message + ' (' + err.field + ')'));
} else {
database.getConnection().done(function (conn) {
conn.query('SELECT COUNT(*) AS beersCount FROM beers WHERE id=?', req.body.id, function (err, rows, fields) {
if (err) {
conn.release();
return next(err);
}
if (rows[0].beersCount > 0) {
conn.release();
return next(new Error('Beer "' + req.body.id + '" already exists!'));
} else {
delete req.body.beerImage;
conn.query('INSERT INTO beers SET ?', req.body, function (err, rows, fields) {
conn.release();
if (err) {
return next(err);
}
res.json({ message: 'Beer "' + req.body.id + '" added!' });
});
}
});
});
}
});
});
module.exports = router;
我找不到先 "parse" 多部分表单数据的方法(以便能够使用 req.body.id 进行查询并检查它是否存在),然后再决定是否要是否上传文件。似乎 "cpUpload" 同时做这两件事!
知道如何先获取 "req.body.id"(进行查询)然后决定是否要上传文件吗?
您必须先上传文件,然后再测试它是否存在。然后保存或删除它
我发现 Multer 上有一个名为 "fileFilter" 的功能,您可以在其中控制接受哪些文件。在这里,我已经能够执行所需的查询以检查该条目是否存在。
- 这就是我在上传到云之前实现
multipart/formdata
文件字段和文本字段验证的方法。我在multer
中的filterFile
函数如下所示: - 注意使用邮递员的表单数据发送的任何数据都被视为
multipart/formdata
。您必须使用 multer 或其他类似的库才能解析表单数据。 - 对于
x-www-form-urlencoded
和raw
来自postman的数据不需要multer来解析。您可以使用body-parser
或 express 内置中间件express.json()
和express.urlencoded({ extended: false, })
解析这些数据
filterFile = async (req, file, cb) => {
// if mimetypes are expected mimetypes
const allowedMimeTypes = ["image/jpeg", "image/jpg", "image/png"];
if (allowedMimeTypes.includes(file.mimetype)) {
// then validate formdata fields
// reject the request with error if any validation fails
try {
let { highlights, specifications, ...rest } = req.body;
// deserializing string into respective javascript object(here into an array datatype) to facilate validation
highlights = JSON.parse(req.body.highlights);
specifications = JSON.parse(req.body.specifications);
// constructing deserialized formdata
const formdata = { highlights, specifications, ...rest };
// using Joi for validation
let skuAndProductResult = await skuAndProductSchema.validateAsync(
formdata
);
if (skuAndProductResult) {
// accept the fields and proceed to the next middleware
cb(null, true);
return;
}
// reject the request with error
cb(true, false);
return;
} catch (err) {
// reject the request with error
cb(err, false);
}
} else {
// To reject this file pass `false`
cb(`${file.mimetype} is not supported`, false);
}
};