I am writing an Express application, and to avoid cluttering my routes.js
file, I have created a separate UploadController
like so:
// UploadController.js
const multer = require('multer')
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/' + file.fieldname + '/')
},
filename: function (req, file, cb) {
cb(null, Date.now() + '-' + file.originalname)
}
})
const upload = multer({
storage: storage
})
module.exports = {
upload
}
Which I use in routes
like so, specifically this is just my registration route as an example:
app.post('/register',
RegistrationPolicy.validate,
UploadController.upload.single('avatar'),
UserController.register)
This works perfectly fine. Ideally though, I need to perform a check that the request type is of multipart/form-data
before the upload runs, and then after the upload is plete, run:
req.body.avatarUri = req.file.destination + req.file.filename
So that the URI of the uploaded file will be stored in my database when UserController.register
is run.
The neatest way I can think of to do this would be to create a custom upload
method in my controller which does the check, the upload operation, and then the URI allocation. The problem is, putting multer in the middle of a function like this:
async upload (req, res, next, field) {
// ...check request type...
multerUpload.single(field)
// ...assign URI...
next()
}
Gives me Error: Route.post() requires a callback function but got a [object Promise]
Is it possible to use multer in the way I describe? Can anyone point out what I may be misunderstanding? I'm new to Node+Express so if I've missed out some needed information let me know.
I am writing an Express application, and to avoid cluttering my routes.js
file, I have created a separate UploadController
like so:
// UploadController.js
const multer = require('multer')
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/' + file.fieldname + '/')
},
filename: function (req, file, cb) {
cb(null, Date.now() + '-' + file.originalname)
}
})
const upload = multer({
storage: storage
})
module.exports = {
upload
}
Which I use in routes
like so, specifically this is just my registration route as an example:
app.post('/register',
RegistrationPolicy.validate,
UploadController.upload.single('avatar'),
UserController.register)
This works perfectly fine. Ideally though, I need to perform a check that the request type is of multipart/form-data
before the upload runs, and then after the upload is plete, run:
req.body.avatarUri = req.file.destination + req.file.filename
So that the URI of the uploaded file will be stored in my database when UserController.register
is run.
The neatest way I can think of to do this would be to create a custom upload
method in my controller which does the check, the upload operation, and then the URI allocation. The problem is, putting multer in the middle of a function like this:
async upload (req, res, next, field) {
// ...check request type...
multerUpload.single(field)
// ...assign URI...
next()
}
Gives me Error: Route.post() requires a callback function but got a [object Promise]
Is it possible to use multer in the way I describe? Can anyone point out what I may be misunderstanding? I'm new to Node+Express so if I've missed out some needed information let me know.
Share Improve this question asked Apr 14, 2018 at 11:42 transiti0narytransiti0nary 5139 silver badges26 bronze badges 1-
Why are you using an
async
function? The Express middleware pattern wantsfunction(request, response, nextCallback){}
. Additionally, the function signature you are providing will be considered an error middleware because it has 4 arguments. Can you show more of your router? – zero298 Commented Apr 16, 2018 at 18:43
1 Answer
Reset to default 7 +50The function that you put forward doesn't meet the signature specification of an Express middleware. The signature needs to be:
function(requestObject, responseObject, nextCallback){}
The return value of the function doesn't really matter (but you are returning a Promise
since you declared it async
). You are passing an Error Middleware because you are giving back a function with 4 arguments.
I think that you should break up the logic to do the request type checking into its own middleware, chain to multer separately, and then do the request transformation in its own middlware as well unless I'm missing something:
function checkMultipart(req, res, next) {
const contentType = req.headers["content-type"];
// Make sure it's multipart/form
if (!contentType || !contentType.includes("multipart/form-data")) {
// Stop middleware chain and send a status
return res.sendStatus(500);
}
next();
}
function rewriter(req, res, next) {
// Set the request fields that you want
req.body.avatarUri = req.file.destination + req.file.filename;
next();
}
router.post("/", checkMultipart, upload.single("avatar"), rewriter, (req, res, next) => {});