【问题标题】:Use Multer file upload within a separate controller function在单独的控制器功能中使用 Multer 文件上传
【发布时间】:2018-09-24 15:25:58
【问题描述】:

我正在编写一个 Express 应用程序,为了避免弄乱我的 routes.js 文件,我创建了一个单独的 UploadController,如下所示:

// 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
}

我在routes这样使用,具体来说这只是我的注册路线作为例子:

app.post('/register',
    RegistrationPolicy.validate,
    UploadController.upload.single('avatar'),
    UserController.register)

这工作得很好。理想情况下,我需要在上传运行之前检查请求类型是否为multipart/form-data,然后在上传完成后运行:

req.body.avatarUri = req.file.destination + req.file.filename

这样当UserController.register运行时,上传文件的URI就会存储在我的数据库中。

我能想到的最简洁的方法是在我的控制器中创建一个自定义的upload 方法,该方法执行检查、上传操作,然后是 URI 分配。问题是,将 multer 放在这样的函数中间:

async upload (req, res, next, field) {
    // ...check request type...
    multerUpload.single(field)
    // ...assign URI...
    next()
}

给我Error: Route.post() requires a callback function but got a [object Promise]

是否可以按照我描述的方式使用 multer?谁能指出我可能会误解什么?我是 Node+Express 的新手,所以如果我错过了一些需要的信息,请告诉我。

【问题讨论】:

  • 你为什么使用async函数? Express 中间件模式需要function(request, response, nextCallback){}。此外,您提供的函数签名将被视为error middleware,因为它有 4 个参数。你能展示更多你的路由器吗?

标签: javascript node.js express multer


【解决方案1】:

您提出的功能不符合 Express 中间件的签名规范。签名必须是:

function(requestObject, responseObject, nextCallback){}

函数的返回值并不重要(但你返回一个Promise,因为你声明了async)。您正在传递一个Error Middleware,因为您正在返回一个带有 4 个参数的函数。


我认为你应该将请求类型检查的逻辑分解到它自己的中间件中,分别链接到 multer,然后在它自己的中间件中进行请求转换,除非我遗漏了什么:

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) => {});

【讨论】:

  • 谢谢。这是我曾经试图做的,但由于某种原因它不起作用。我想我只是在某个地方做错了什么而没有注意到,因为已经是深夜了。如果我再次遇到问题,我会重试并返回。
  • 这应该可行,这也是这样做的方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-02
  • 2019-07-31
  • 2017-03-29
  • 2013-04-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多