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;
关键修改点
- 替换
fs.createReadStream(file.path)为直接使用file.stream,复用Multer传递的文件原始可读流 - 新增文件扩展名提取逻辑,避免哈希文件名丢失格式信息
- 无需额外创建磁盘读取流,直接通过内存流完成哈希计算
内容的提问来源于stack exchange,提问作者EhsanKey_
相关产品推荐
相关产品推荐

