React/NestJS多文件上传报400错误:无法同时上传CV与头像
解决NestJS+React同时上传两个文件时的400 Bad Request错误
你遇到的核心问题是NestJS中不能同时使用多个FileInterceptor。FileInterceptor专门用于处理单个文件上传,叠加使用时第二个拦截器会覆盖第一个的请求解析逻辑,导致其中一个文件无法被正确捕获,触发后端校验失败返回400错误。
后端NestJS代码修复
使用FieldsInterceptor替代多个FileInterceptor,它支持同时处理多个不同字段的文件上传:
- 先导入所需的拦截器和装饰器:
import { FieldsInterceptor, UploadedFiles } from '@nestjs/platform-express';
- 修改接口的拦截器配置与参数获取逻辑:
@Post('signup') @UseInterceptors(FieldsInterceptor([ { name: 'cv', maxCount: 1 }, { name: 'avatarImage', maxCount: 1 }, ])) async signUp( @Body() signupDto: SignupDto, @UploadedFiles() files: { cv?: Express.Multer.File[], avatarImage?: Express.Multer.File[] }, ): Promise<any> { // 提取单个文件(maxCount设为1,数组第一个元素即为目标文件) const cv = files.cv?.[0]; const avatarImage = files.avatarImage?.[0]; if (!cv) { throw new Error('CV file is required.'); } signupDto.cvFileName = cv.originalname; signupDto.cvFileBuffer = cv.buffer; signupDto.cv = await this.fileUploadService.uploadFileCv( signupDto.cvFileName, signupDto.cvFileBuffer, ); if (!avatarImage) { throw new Error('Avatar Image is required'); } signupDto.avatarImageName = avatarImage.originalname; signupDto.avatarImageFileBuffer = avatarImage.buffer; signupDto.avatarImage = await this.fileUploadService.uploadImage( signupDto.avatarImageName, signupDto.avatarImageFileBuffer, ); return this.userService.createUser(signupDto); }
前端React代码优化
前端逻辑整体无大问题,可做两处优化避免潜在bug:
- 仅在存在有效文件时才添加到FormData,避免传入空字符串
- 校验文件类型,确保是合法的
File对象
修改后的handleRegistration:
const handleRegistration = async (event: FormEvent<HTMLFormElement>) => { event.preventDefault(); const formData = new FormData(); // 仅添加有效文件 if (selectedCvFile.length > 0 && selectedCvFile[0] instanceof File) { formData.append("cv", selectedCvFile[0]); } if (selectedImagesForAvatar.length > 0 && selectedImagesForAvatar[0] instanceof File) { formData.append("avatarImage", selectedImagesForAvatar[0]); } // 仅添加有值的表单字段 Object.entries(formState).forEach(([key, value]) => { if (value) { formData.append(key, value); } }); dispatch({ type: "CLEAR_ALERTS" }); try { const response = await fetch("http://localhost:3000/auth/signup", { method: "POST", body: formData, }); const data = await response.json(); if (response.ok) { dispatch({ type: "SHOW_SUCCESS", payload: `You have registered correctly !`, }); console.log(data); localStorage.setItem("token", data.accessToken); } else { dispatch({ type: "SHOW_ERROR", payload: response.statusText }); console.error("Registration failed:", response.statusText, response); } } catch (error) { console.error("Error during registration:", error); } };
内容的提问来源于stack exchange,提问作者Soulofcinder
相关产品推荐
相关产品推荐

