React对接Spring API:MultipartFile上传失败问题排查
React前端与Spring后端MultipartFile上传失败排查与修复
问题现象
React前端向Spring后端上传图片时,后端抛出org.springframework.web.multipart.MultipartException: Current request is not a multipart request错误,但用Postman测试相同接口完全正常。
原代码片段
Spring后端接口代码
@PostMapping("/save") public ResponseEntity<?> save(@RequestParam(required = false) String folderId, @RequestParam MultipartFile multipartFile) throws IOException{ // 文件夹存在校验 int id = Integer.parseInt(folderId); Optional<Folder> folderOpt = folderService.get(id); if(folderOpt.isEmpty()){ return new ResponseEntity<>("The folder does not exist", HttpStatus.NOT_FOUND); } Folder folder = folderOpt.get(); // 图片有效性校验 BufferedImage bi = ImageIO.read(multipartFile.getInputStream()); if (bi == null){ return new ResponseEntity("Image does not valid", HttpStatus.BAD_REQUEST); } Map result = cloudinaryService.upload(multipartFile); // 保存到数据库 Image img = new Image( (String)result.get("original_filename"), (String)result.get("url"), (String)result.get("public_id") ); img.setFolder(folder); imageService.save(img); return new ResponseEntity<>(HttpStatus.OK); }
React前端组件代码
const [imageSelected,setImageSelected] = useState("") const uploadImage = (files) =>{ const formData = new FormData(); formData.append("file", files[0]); console.log(formData) ImagenServices.postImage(formData,id) } return( <div className={Styles.container}> <div> <input type="file" id="myFileField" onChange={(event) => {setImageSelected(event.target.files)}}/> <button onClick={() => uploadImage(imageSelected)}>Upload image</button> </div> </div> )
PostImage服务代码
async postImage(file,idFolder){ let request = await fetch(REST_API_URL + "/save",{ method: "POST", body:{ 'folderId': idFolder, 'multipartFile': file }, headers:{ 'Accept': 'application/json, text/plain, */*', 'Content-Type': false }}, ) }
报错信息
ERROR 95787 --- [io-8080-exec-10] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Current request is not a multipart request] with root cause
org.springframework.web.multipart.MultipartException: Current request is not a multipart request
at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValueInternal(RequestParamMethodArgumentResolver.java:210) ~[spring-web-5.3.22.jar:5.3.22]
错误原因分析
- FormData参数名不匹配:后端
@RequestParam接收的参数名是multipartFile,但前端append的是file,导致后端无法识别文件参数。 - 请求body格式错误:PostImage服务中把FormData嵌套在了普通对象里,而非直接作为请求body,浏览器无法识别为multipart请求。
- Content-Type设置错误:手动设置
Content-Type: false会破坏浏览器自动生成的multipart/form-data请求头(包含必要的boundary信息)。 - useState初始值不合理:
imageSelected初始值设为空字符串,而event.target.files是FileList类型,类型不匹配可能导致后续逻辑异常。
修正后的代码
React前端组件代码
const [imageSelected, setImageSelected] = useState(null); // 初始值设为null,匹配FileList类型 const uploadImage = () => { if (!imageSelected) return; // 增加文件选择校验 const formData = new FormData(); formData.append("multipartFile", imageSelected[0]); // 参数名与后端保持一致 formData.append("folderId", id); // 将folderId也加入FormData ImagenServices.postImage(formData); }; return ( <div className={Styles.container}> <div> <input type="file" id="myFileField" onChange={(event) => setImageSelected(event.target.files)} /> <button onClick={uploadImage}>Upload image</button> </div> </div> );
PostImage服务代码
async postImage(formData) { const request = await fetch(REST_API_URL + "/save", { method: "POST", body: formData, // 直接传递FormData实例 headers: { 'Accept': 'application/json, text/plain, */*' // 不要手动设置Content-Type,浏览器会自动添加正确的multipart/form-data头 } }); // 可根据需求添加响应处理逻辑 const response = await request.json(); return response; }
关键修复点说明
- 参数名一致性:确保FormData中append的参数名与后端
@RequestParam的参数名完全一致。 - 正确传递FormData:必须将FormData直接作为fetch的body,不能嵌套在其他对象中,否则浏览器无法识别为multipart请求。
- 自动处理Content-Type:当请求body是FormData时,浏览器会自动生成包含boundary的
multipart/form-data请求头,手动设置反而会导致请求格式错误。 - 类型匹配的状态初始值:将
imageSelected初始值设为null,避免与FileList类型冲突。
内容的提问来源于stack exchange,提问作者ddi02
相关产品推荐
相关产品推荐

