最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Use Multer file upload within a separate controller function - Stack Overflow

programmeradmin4浏览0评论

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 wants function(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
Add a ment  | 

1 Answer 1

Reset to default 7 +50

The 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) => {});
发布评论

评论列表(0)

  1. 暂无评论