Angular对接Spring Boot表单(无需传图片)保存报错的解决求助
问题描述
原本打算实现带图片的注册表单保存功能,Spring Boot REST API在Postman中可正常运行,但现在希望仅保存数据而不上传图片,Angular端对接时出现以下报错:
- POST http://localhost:8080/patient/post 400 (Bad Request)
- Resolved [org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'image' is not present]
相关代码
Spring Controller类
@RestController @RequestMapping("/patient/") @CrossOrigin(origins = "http://localhost:4200", allowCredentials = "true") public class PatientRegistrationController { @Autowired PatientRegistrationService registrationService; static String path = "F:\\patientPhoto\\"; @PostMapping("post") @RequestParam. public void createPatient(@RequestParam("patInfo") String patInfo, @RequestParam("image") MultipartFile image) { String fullPath = path+image.getOriginalFilename(); PatientRegistrationEntity patient = objectMapperReadValue(patInfo,PatientRegistrationEntity.class); try { image.transferTo(new File(fullPath)); //save to pc hdd } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } patient.setPatinetPhotoPaht(fullPath); //save path name to database registrationService.savepatient(patient); } }
Angular Service类
export class PatientServiceService { private api = "http://localhost:8080"; constructor(private http: HttpClient) { } public getpatinetList(): Observable<patientIface[]>{ return this.http.get<patientIface[]>(`${this.api}/patient/post`); } private _refreshNeeds = new Subject<void>(); get refreshNeeds(){ return this._refreshNeeds; } public addPatient(patientRegistration: patientIface, image:File): Observable<patientIface>{ const patInfo = JSON.stringify(patientRegistration); console.log(typeof patInfo); const formData = new FormData(); formData.append('patInfo', patInfo); formData.append('image', image); return this.http.post<patientIface>(`${this.api}/patient/post`, formData).pipe( tap( () => { this._refreshNeeds.next(); } ) ); }
组件代码
createpatient() { // console.log(this.patientForm.value.dateOfBirth.toLocaleDateString()); this.patientForm.value.dateOfBirth = this.patientForm.value.dateOfBirth?.toLocaleDateString(); console.log("this.patientForm.value", this.patientForm.value); const imageFile = this.patientForm.value.patientImage; this.patientService.addPatient(this.patientForm.value, imageFile).subscribe( (data: patientIface) => { console.log("data", data); this.router.navigate(["patient-table"]) } ); }
解决方案
问题核心是Spring后端将image参数设为必填,同时前端无论是否有图片都会传递该参数,导致无图片时触发错误。需前后端同步修改:
1. Spring Boot后端修改
调整请求参数为可选
将@RequestParam("image") MultipartFile image改为@RequestParam(value = "image", required = false) MultipartFile image,让图片参数变为非必填。
适配无图片的业务逻辑
仅当图片存在且非空时,执行文件保存和路径设置;无图片时直接跳过图片处理逻辑。
修改后的Controller代码:
@RestController @RequestMapping("/patient/") @CrossOrigin(origins = "http://localhost:4200", allowCredentials = "true") public class PatientRegistrationController { @Autowired PatientRegistrationService registrationService; @Autowired private ObjectMapper objectMapper; // 补充注入ObjectMapper,修复原代码的方法调用错误 static String path = "F:\\patientPhoto\\"; @PostMapping("post") public void createPatient(@RequestParam("patInfo") String patInfo, @RequestParam(value = "image", required = false) MultipartFile image) { // 解析患者信息 PatientRegistrationEntity patient = objectMapper.readValue(patInfo, PatientRegistrationEntity.class); // 仅当图片存在且非空时处理 if (image != null && !image.isEmpty()) { String fullPath = path + image.getOriginalFilename(); try { image.transferTo(new File(fullPath)); // 保存图片到本地 } catch (IllegalStateException | IOException e) { e.printStackTrace(); } patient.setPatinetPhotoPaht(fullPath); // 保存图片路径到数据库 } else { // 无图片时设置路径为null或空字符串,根据业务需求调整 patient.setPatinetPhotoPaht(null); } registrationService.savepatient(patient); } }
2. Angular前端修改
允许图片参数为空
修改addPatient方法,仅当图片存在时才将其添加到FormData中:
public addPatient(patientRegistration: patientIface, image?: File): Observable<patientIface>{ const patInfo = JSON.stringify(patientRegistration); const formData = new FormData(); formData.append('patInfo', patInfo); // 仅当图片存在且大小大于0时添加到表单 if (image && image.size > 0) { formData.append('image', image); } return this.http.post<patientIface>(`${this.api}/patient/post`, formData).pipe( tap( () => { this._refreshNeeds.next(); } ) ); }
组件中处理无图片场景
确保未选择图片时传递的参数为undefined,避免传递空文件对象:
createpatient() { this.patientForm.value.dateOfBirth = this.patientForm.value.dateOfBirth?.toLocaleDateString(); console.log("this.patientForm.value", this.patientForm.value); // 无图片时传递undefined const imageFile = this.patientForm.value.patientImage ? this.patientForm.value.patientImage : undefined; this.patientService.addPatient(this.patientForm.value, imageFile).subscribe( (data: patientIface) => { console.log("data", data); this.router.navigate(["patient-table"]) } ); }
内容的提问来源于stack exchange,提问作者Mahadi Hasan
相关产品推荐
相关产品推荐

