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

NestJS用Buffer+Multer传图至Mongoose失败:提示image必填

问题描述

在NestJS中尝试将图片(以Buffer形式)和房间信息一同存入Mongoose数据库时,图片已成功保存到项目uploads目录,但Mongoose报错:rooms validation failed: image: Path 'image' is required,数据无法写入数据库。

错误原因

核心问题是Mongoose的验证时机:你直接把@Body()接收的room对象传入RoomModel.create(),Mongoose会先对该对象做必填字段校验,而你是在校验之后才给room.image赋值,导致校验阶段image字段为空,触发必填项验证失败。

解决方案

  1. 使用DTO接收请求体:用RoomDto(数据传输对象)接收前端传来的房间信息,而非直接使用Mongoose实体类rooms,既规范又避免验证冲突。
  2. 合并数据后创建文档:在服务层将房间DTO数据和图片Buffer合并为新对象,再传入create()方法,确保Mongoose校验时image字段已存在。

修改后的room.service.ts

import { Injectable, UnauthorizedException } from '@nestjs/common';
import mongoose from 'mongoose';
import { rooms } from './schemas/schema.room';
import { InjectModel } from '@nestjs/mongoose';
import { RoomDto } from './dto/room.dto';

@Injectable()
export class RoomService {
    constructor(
        @InjectModel(rooms.name)
        private RoomModel: mongoose.Model<rooms>
    ){}

    async findAll(): Promise<rooms[]>{
        const rooms = await this.RoomModel.find();
        return rooms;
    }

    async create(roomDto: RoomDto, imageFile: Express.Multer.File): Promise<rooms>{
        if(!imageFile){
            throw new UnauthorizedException("未上传图片")
        }
        
        // 合并房间数据与图片Buffer,生成待入库对象
        const roomData = {
            ...roomDto,
            image: imageFile.buffer
        };
        const res = await this.RoomModel.create(roomData);
        return res;
    }
}

修改后的room.controller.ts

import { Body, Controller, Get, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
import { RoomService } from './room.service';
import { rooms } from './schemas/schema.room';
import { FileInterceptor } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import { RoomDto } from './dto/room.dto';

@Controller('room')
export class RoomController {
    constructor(
        private roomService: RoomService
    ){}

@Get()
async getAllrooms(): Promise<rooms[]>{
    return this.roomService.findAll()
}

@Post()
@UseInterceptors(
  FileInterceptor('image', {
      storage: diskStorage({
          destination: './uploads',
          filename: (req, file, cb) => {
              const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
              cb(null, file.fieldname + '-' + uniqueSuffix);
          },
      }),
  }),
)
async createrooms(
    @Body() roomDto: RoomDto,
    @UploadedFile() imageFile: Express.Multer.File,
): Promise<rooms>{
    return this.roomService.create(roomDto, imageFile);
}
}

补充RoomDto示例(若未完善)

// src/room/dto/room.dto.ts
import { IsBoolean, IsNumber, IsString } from 'class-validator';

export class RoomDto {
    @IsNumber()
    roomNo: number;

    @IsString()
    type: string;

    @IsNumber()
    price: number;

    @IsBoolean()
    status: boolean;

    @IsString()
    description: string;

    // image字段无需在此定义,由文件上传模块处理
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 09:12:49