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

multer.js文件上传path参数类型无效错误及重复存储问题

解决Multer中file.path未定义导致的文件哈希计算错误

我尝试通过计算文件哈希值避免重复存储,但在Multer的filename回调里访问file.path时出现类型错误,错误信息如下:

{"error":{"code":"ERR_INVALID_ARG_TYPE"},"exception":true,"level":"error","message":"uncaughtException: The \"path\" argument must be of type string or an instance of Buffer or URL. Received undefined\nTypeError [ERR_INVALID_ARG_TYPE]: The \"path\" argument must be of type string or an instance of Buffer or URL. Received undefined\n at new ReadStream (node:internal/fs/streams:171:5)\n at Object.createReadStream (node:fs:2935:10)\n at DiskStorage.filename [as getFilename] (D:\chatAppServer\src\middleware\middlewareUploads.js:32:23)\n at D:\chatAppServer\node_modules\multer\storage\disk.js:34:10\n at DiskStorage.destination [as getDestination]"}

原代码:

const fs = require("fs");
const multer = require("multer");
const crypto = require("crypto");

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const type = file.mimetype.split("/")[0];
    const path = `./upload/${req.user._id}/${type}`;
    fs.mkdirSync(path, { recursive: true });
    cb(null, path);
  },
  filename: (req, file, cb) => {
    const hash = crypto.createHash("sha256");
    const stream = fs.createReadStream(file.path);

    stream.on("data", (data) => {
      hash.update(data);
    });

    stream.on("end", () => {
      const fileHash = hash.digest("hex");
      const fileName = `${fileHash}${file.originalname}`;
      cb(null, fileName);
    });

    stream.on("error", (error) => {
      cb(error);
    });
  },
});

const upload = multer({ storage });

module.exports = upload;

问题原因

Multer的diskStorage流程中,filename回调执行早于文件写入磁盘的操作,此时file.path还未被赋值,自然是undefined,无法用它创建读取流。

修复方案

直接使用Multer提供的file.stream(文件的可读流)来计算哈希,无需依赖磁盘路径:

const fs = require("fs");
const multer = require("multer");
const crypto = require("crypto");

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const type = file.mimetype.split("/")[0];
    const path = `./upload/${req.user._id}/${type}`;
    fs.mkdirSync(path, { recursive: true });
    cb(null, path);
  },
  filename: (req, file, cb) => {
    const hash = crypto.createHash("sha256");
    
    // 使用file.stream替代file.path
    file.stream.on("data", (data) => {
      hash.update(data);
    });

    file.stream.on("end", () => {
      const fileHash = hash.digest("hex");
      // 提取文件扩展名,避免丢失格式信息
      const ext = file.originalname.split(".").pop();
      const fileName = `${fileHash}.${ext}`;
      cb(null, fileName);
    });

    file.stream.on("error", (error) => {
      cb(error);
    });
  },
});

const upload = multer({ storage });

module.exports = upload;

关键修改点

  1. 替换fs.createReadStream(file.path)为直接使用file.stream,复用Multer传递的文件原始可读流
  2. 新增文件扩展名提取逻辑,避免哈希文件名丢失格式信息
  3. 无需额外创建磁盘读取流,直接通过内存流完成哈希计算

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 14:56:32