Node.js Can';t在控制器中正确使用Multer(Node/Express.js)

Node.js Can';t在控制器中正确使用Multer(Node/Express.js),node.js,express,multer,Node.js,Express,Multer,我在使用Multer上传文件时遇到了问题,不幸的是,我对Multer没有太多经验。 在这个项目中,我试图构建一些东西,比如路由调用运行命令的函数(控制器),例如创建产品等等 我很确定我正确地设置了Multer,但是当我尝试在控制器中req.file.filename时,它会返回一个未定义的值 这是我的设置(目前Multer是一个助手函数,之后我将把它移到中间件中,因为这是不正确的) 文件存储辅助功能 const multer = require("multer"); //S

我在使用Multer上传文件时遇到了问题,不幸的是,我对Multer没有太多经验。 在这个项目中,我试图构建一些东西,比如路由调用运行命令的函数(控制器),例如创建产品等等

我很确定我正确地设置了Multer,但是当我尝试在控制器中req.file.filename时,它会返回一个未定义的值

这是我的设置(目前Multer是一个助手函数,之后我将把它移到中间件中,因为这是不正确的)

文件存储辅助功能

const multer = require("multer");

//SET Storage
let storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "public/uploads");
  },
  filename: function (req, file, cb) {
    const fileName = file.originalname.replace(" ", "-");
    cb(null, fileName + "-" + Date.now());
  },
});
const uploadOptions = multer({ storage });

module.exports = { uploadOptions };
产品路由器

const express = require("express");
const router = express.Router();

//@Helpers
const { uploadOptions } = require("./../../Helpers/FileStorage.helper");

//@Categories
const {
  getProducts,
  postProduct
} = require("./../../Controllers/Products/product.controller");

//GET ALL Products + ADD NEW Product
router
  .get("/", getProducts)
  .post("/", uploadOptions.single("image"), postProduct);
最后是后期产品控制器:

//POST A New Product
const postProduct = expressAsyncHandler(async (req, res) => {
  const category = await Categories.findOne(req.body.category);
  if (!category) return res.status(400).send("Category is invalid, try again!");


  const fileName = req.file.filename;
  const basePath = `${req.protocol}://${req.get("host")}/public/upload/`;

  const product = new Product({
    name: req.body.name,
    description: req.body.description,
    richDescription: req.body.richDescription,
    image: `${basePath}${fileName}`,
    brand: req.body.brand,
    price: req.body.price,
    category,
    countInStock: req.body.countInStock,
    rating: req.body.rating,
    numReviews: req.body.numReviews,
    isFeatured: req.body.isFeatured,
  });
  const productList = await Product.findOne({ name: product.name });
  if (productList != null) {
    return res.status(404).send("Product already exists! Please try again!");
  }
  try {
    await product.save();
    res.status(200).send(product);
  } catch (e) {
    res.status(500).send("Product was not created! Error: " + e.message);
  }
});
我知道在routes中执行此操作的传统方法如下(这很有效!)

然而,正如我上面提到的,我试图将路由操作分解为控制器函数。 当console.log(req.file)返回未定义的

我怀疑这些道具没有被传递到postProduct函数,这就是导致错误的原因,但我不知道如何解决这个问题。我已经盯着这个太久了,也许这是一件容易解决的事情,我很愚蠢(很可能)

如果有人能帮我解决这个问题,并解释我哪里出了问题,我将永远感激


编辑:这是错误:“TypeError:无法读取未定义的”的属性“filename”

此语句:
return console.log(req.file)
中的
postProduct
阻止其余代码运行并返回
void
。始终返回
void

如果您只想记录文件并继续函数的其余部分,请删除
return
关键字:
console.log(req.file)


运行应用程序时,console.log在终端中输出了什么?

我认为您没有正确解析表单数据:

// this is for parsing json data
app.use(express.json());
// this is for parsing form data
app.use(express.urlencoded({ extended: false }));

console.log()
的返回类型是
void
。这就是函数返回未定义的
的原因。控制台上的输出是否也未定义?是的,它也返回未定义。您好,我这样做是因为在放置console.log之前,它不会继续,因为req.file.filename未定义。所以我想看看这个文件是否被注册(事实并非如此)。当我删除上述问题时,问题就出现了。完整错误:“TypeError:无法读取未定义的属性'filename'”为了清晰起见,我将其添加到文章底部。我明白了。这可能与
expressAsyncHandler
有关。尝试从
postProduct
中删除它,并在路由中使用它:
.post(“/”,uploadOptions.single(“image”),expressAsyncHandler(postProduct))
只是为了澄清一下,使用multer的传统方法是处理完全相同的请求吗?然后我们可以排除前端、文件和其他东西。嘿-我只是尝试了一下,可惜没有成功:(-如果有帮助,这里是回复:为什么这是公认的答案?OP说他是在处理文件上传(多部分/表单数据),而不是urlencoded实体(application/x-www-form-urlencoded)。
// this is for parsing json data
app.use(express.json());
// this is for parsing form data
app.use(express.urlencoded({ extended: false }));