You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Multer v2.0.0+Express上传图片遇ERR_INVALID_ARG_TYPE错误求助

问题

上传图片时触发错误:

[ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string or an instance of Buffer or URL. Received null

技术栈为Multer v2.0.0 + Express,不确定是版本问题还是await pipeline()的问题。

相关代码如下:

upload.js

const UserModel = require("../models/user.model");
const fs = require("fs");
const { promisify } = require("util");
const pipeline = promisify(require("stream").pipeline);
const { uploadErrors } = require("../utils/errors.utils");

module.exports.uploadProfile = async (req, res) => {
  try {
    if (
      req.file.detectedMimeType != "image/jpg" &&
      req.file.detectedMimeType != "image/png" &&
      req.file.detectedMimeType != "image/jpeg"
    )
      throw Error("invalid file");

    if (req.file.size > 500000) throw Error("max size");
  } catch (err) {
    const errors = uploadErrors(err);
    return res.status(201).json({ errors });
  }
  const fileName = req.body.name + ".jpg";

  await pipeline(
    req.file.stream,
    fs.createWriteStream(
      `${__dirname}/../client/public/uploads/profil/${fileName}`
    )
  );
};

user.routes.js

const router = require("express").Router();
const multer = require("multer");
const upload = multer();
const userController = require("../controllers/user.controller");
const authController = require("../controllers/auth.controller");
const uploadController = require("../controllers/upload.controller");

// auth
router.post("/register", authController.signUp);
router.post("/login", authController.signIn);
router.get("/logout", authController.logout);
//user display block
router.get("/", userController.getAllUsers);
router.get("/:id", userController.userInfo);
router.put("/:id", userController.updateUser);
router.delete("/:id", userController.deleteUser);
router.patch("/follow/:id", userController.follow);
router.patch("/unfollow/:id", userController.unfollow);
// upload
router.post("/upload", upload.single("file"), uploadController.uploadProfile);
module.exports = router;

排查与解决

错误核心是fs.createWriteStream接收的路径参数为无效值(null/undefined),以下是具体排查点和修复方案:

1. 配置Express Body解析中间件

Multer v2不会自动解析非文件字段,若未配置body解析,req.body会是空对象,导致req.body.name为undefined,拼接后生成无效文件名。在Express主文件中添加:

const express = require('express');
const app = express();

// 解析表单格式请求体
app.use(express.urlencoded({ extended: true }));
// 若客户端用JSON传递数据,需添加此配置
app.use(express.json());

2. 校验req.body.name有效性

在生成文件名前,先检查字段是否存在,避免生成无效路径:

// 在pipeline逻辑前添加
if (!req.body.name) {
  return res.status(400).json({ error: 'name字段不能为空' });
}
const fileName = req.body.name + ".jpg";

3. 确保目标目录存在

若写入文件的目标目录不存在,fs.createWriteStream会抛出异常,提前递归创建目录:

const path = require('path');
// 生成绝对路径,避免相对路径出错
const targetDir = path.join(__dirname, '../client/public/uploads/profil');
if (!fs.existsSync(targetDir)) {
  fs.mkdirSync(targetDir, { recursive: true });
}

// 替换原pipeline中的路径
await pipeline(
  req.file.stream,
  fs.createWriteStream(path.join(targetDir, fileName))
);

4. 完善pipeline错误捕获

原代码未处理pipeline执行错误,添加try-catch捕获写入异常:

try {
  await pipeline(
    req.file.stream,
    fs.createWriteStream(path.join(targetDir, fileName))
  );
  // 可在此添加数据库更新逻辑,比如将文件名关联到用户
  res.status(200).json({ message: '上传成功', fileName });
} catch (pipeErr) {
  res.status(500).json({ error: '文件写入失败', details: pipeErr.message });
}

5. 确认Multer字段名匹配

确保客户端上传的文件字段名是file,与路由中upload.single("file")的参数一致,否则req.file会为null,提前触发其他错误。


内容的提问来源于stack exchange,提问作者user19363667

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 11:27:27