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字段为空,触发必填项验证失败。
解决方案
- 使用DTO接收请求体:用
RoomDto(数据传输对象)接收前端传来的房间信息,而非直接使用Mongoose实体类rooms,既规范又避免验证冲突。 - 合并数据后创建文档:在服务层将房间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
相关产品推荐
相关产品推荐

