Nodejs Multer - 上传多个文件时接收404并且无法设置标题

时间:2018-04-23 13:54:46

标签: node.js http-status-code-404 multer

我收到404 Not Found和"错误[ERR_HTTP_HEADERS_SENT]:无法在将标题发送到客户端后设置标题"当我尝试提交上传了两张图片的表单时。这两个图像都不是必填字段,因此当我上传一个图像(可以是其中一个)时,一切正常,我也不会收到错误。只有在一个请求中上传两者时才会出现此问题。检查我的上传文件夹,当我收到404时,两张图片都被正确上传。

以下是multer的代码:

const multerOptions = {
  storage: multer.memoryStorage(),
  fileFilter(req, file, next) {
    const isPhoto = file.mimetype.startsWith('image/');
    if (isPhoto) {
      next(null, true);
    } else {
      next({ message: 'That filetype isn\'t allowed!' }, false);
    }
  },
};

export const upload = multer(multerOptions).fields([
  { name: 'avatar' },
  { name: 'accolade' },
]);

export const resize = async (req, res, next) => {
  if (!req.files) {
    next();
    return;
  }
  Object.keys(req.files).forEach(async (file) => {
    const extension = req.files[file][0].mimetype.split('/')[1];
    req.body[file] = `${uuid.v4()}.${extension}`;
    const uploaded = await jimp.read(req.files[file][0].buffer);
    if (file === 'avatar') {
      await uploaded.resize(300, jimp.AUTO);
    } else if (file === 'accolade') {
      await uploaded.resize(30, jimp.AUTO);
    }
    await uploaded.write(`./public/uploads/${req.body[file]}`);
    next();
  });
};

这是路线:

router.post(
  '/team-members/add/:id',
  authController.authCheck,
  userController.isAdmin,
  userController.upload,
  userController.resize,
  userController.validateUser,
  catchErrors(userController.addTeamMember),
);

以下是路由中的其他中间件方法:

export const authCheck = (req, res, next) => {
  (req.isAuthenticated()) ? next() : res.redirect('/login');
};

export const isAdmin = (req, res, next) => {
  (req.user.role !== 'admin') ? res.redirect('/dashboard') : next();
};

export const validateUser = (req, res, next) => {
  req.checkBody('firstName', 'There must be a first name!').notEmpty();
  req.checkBody('lastName', 'There must be a last name!').notEmpty();
  req.checkBody('email', 'There must be an email!').notEmpty();
  req.checkBody('role', 'A role must be specified!').notEmpty();

  const errors = req.validationErrors();
  if (errors) {
    req.flash('error', errors.map(err => err.msg));
    res.redirect('back');
  }
  next();
};

最后添加用户的功能(它包含在捕获错误而不是在控制器中捕获错误的函数中):

export const addTeamMember = async (req, res) => {
  const org = await Org.findOne({ _id: req.params.id });
  if (org) {
    const newUser = new User(req.body);
    newUser.organization = org._id;
    newUser.invitation = true;
    await newUser.save();
    await org.update({ $push: { users: newUser } });

    const inviteLink = `http://${req.headers.host}/join/${org._id}`;
    await send({
      user: newUser,
      filename: 'invitation',
      subject: `Welcome ${newUser.email}`,
      inviteLink,
    });
    req.flash('success', `Yay! An invitation has been sent to ${newUser.email}`);
    res.redirect(`/team-members/${org._id}`);
  } else {
    req.flash('error', 'No organization found!');
    req.redirect('back');
  }
};

我只在一个请求中上传了头像和荣誉时才收到错误。如果我只在一个请求中上传一个,我就没有错误。在这两种情况下,图像都会上传到我指定的上传目录中,用户会被添加到我的数据库中,并会触发邀请电子邮件。成功的重定向是对具有相同authCheck和isAdmin中间件的视图的单个GET请求。

我已经完成并注释掉了提交请求所必需的代码部分(checkAuth,isAdmin,validateUser和发送电子邮件),但只要我上传两个请求,我就会得到一个错误。我出错了什么想法?

1 个答案:

答案 0 :(得分:0)

发布答案以防万一其他人绊倒。

next()调用位于resize方法中的forEach块内,因此正在为每个正在上载的文件调用它。将它移到街区外(显然)解决了这个问题。