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

Next.js使用Multer上传图片时req.file始终为undefined的问题

问题:Next.js中Multer无法获取上传文件(req.file为undefined)

我用Next.js全栈开发一个带多字段的表单,其中包含图片上传字段(与Mongoose Schema字段名一致)。流程是:先用Multer把图片传到本地服务器拿到路径,再将该路径传给Cloudinary完成上传,最后把Cloudinary返回的URL存入数据库。

目前遇到的问题是:明明表单已发送图片,但req.file始终返回undefined。最初未使用next-connect,尝试用Promise.resolve调用upload函数,后来改用handler后问题依旧。我需要Multer返回本地文件路径,才能继续后续的Cloudinary上传流程。


相关代码

/client/middleware/multer.js

import multer from "multer";
import fs from 'fs';
import path from 'path';

const uploadDir = './public/assets/upload';

// 确保上传目录存在
if (!fs.existsSync(uploadDir)){
    fs.mkdirSync(uploadDir, { recursive: true });
}

// 配置multer存储
console.log("welcome from multer")// 日志用于检查存储函数是否被调用
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    console.log("Multer: Saving to local directory");
    cb(null, uploadDir); // 文件保存到指定目录
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + path.extname(file.originalname)); // 生成唯一文件名
  }
});
console.log("bye from multer")
export const upload = multer({ storage: storage });

/client/app/api/users/profile/route.js

import { createRouter } from 'next-connect';
import { connect } from '@dbConfig/dbConfig';
import User from '@models/UserModel';
import { upload } from '@middleware/multer';
import { uploadOnCloudinary } from '@helpers/cloudinary';

// 连接数据库
connect();

// 创建next-connect路由
const handler = createRouter();

// 使用multer处理文件上传的中间件
handler.use(upload.single('image')); // 'image'对应form-data中的键名

export const config = {
    api: {
        bodyParser: false // 禁用自动解析body,因为用了multer
    }
};

// POST请求处理函数
export async function POST(req, res) {
    try {
        // 检查文件是否存在
        if (!req.file) {
            return res.status(400).json({ error: "No file uploaded" });
        }

        // 获取本地文件路径
        const profilePhotoLocalPath = req.file.path;

        // 从req.body获取其他字段(multer会自动解析文本字段)
        const { id, username, highlights, designation, institute, bio } = req.body;

        // 打印表单数据用于调试
        console.log("Form Data Received: ", {
            id, username, highlights, designation, institute, bio
        });

        // 验证id是否存在
        if (!id) {
            return res.status(400).json({ error: "User ID is required" });
        }

        // 查询用户并更新资料
        const user = await User.findOneAndUpdate(
            { _id: id },
            { username, highlights, designation, institute, bio },
            { new: true }
        );

        if (!user) {
            return res.status(404).json({ error: "User doesn't exist" });
        }

        // 上传头像到Cloudinary
        const avatar = await uploadOnCloudinary(profilePhotoLocalPath);

        if (avatar?.url) {
            user.profilePhoto = avatar.url;
            await user.save();
        }

        return res.status(200).json({
            message: "Profile details updated successfully",
            success: true,
            user
        });
    } catch (error) {
        console.log("Error in the API route:", error);
        return res.status(500).json({ error: error.message });
    }
}

解决方法

1. 修正next-connect的使用逻辑

你创建了handler但未将其与POST请求关联,Next.js App Router中next-connect的正确用法是直接通过handler定义请求方法:

修改/client/app/api/users/profile/route.js:

// 删除原来单独的POST函数,替换为:
handler.post(async (req, res) => {
    // 原POST函数内的所有代码移到这里
});

export default handler.handler();

2. 验证前端请求格式

  • 前端必须以multipart/form-data格式发送请求,不能用application/json
  • 表单图片字段的name属性必须是image,与upload.single('image')的参数一致
  • 确认前端正确构造FormData:
    const formData = new FormData();
    formData.append('image', file); // file为用户选择的文件对象
    formData.append('id', userId);
    // 其他字段依次通过append添加
    

3. 修复Multer存储路径(避免相对路径问题)

将相对路径改为绝对路径,适配不同系统:

// 在multer.js中修改uploadDir定义
const uploadDir = path.join(process.cwd(), 'public', 'assets', 'upload');

4. 确认中间件生效

添加调试中间件,检查Multer是否处理了请求:

// 在route.js的handler.use之后添加
handler.use(upload.single('image'))
.use((req, res, next) => {
    console.log('Multer处理后的req.file:', req.file);
    next();
});

5. 检查Next.js的config配置

确保export const config位置正确,且确实禁用了bodyParser。如果bodyParser未禁用,Next.js会先解析请求,导致Multer无法获取文件流。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 14:20:25