添加@CrossOrigin注解后仍遇CORS错误,请求排查解决
问题描述
Spring Boot后端存在两个接口:用户注册接口可正常处理Angular前端请求,但文件上传接口触发CORS Missing Allow Origin错误。两个控制器均添加了@CrossOrigin(origins = "http://localhost:4200")注解,Postman测试所有接口正常,怀疑是重复@CrossOrigin注解导致问题,请求排查并解决。
相关代码如下:
后端文件上传控制器
@RestController @RequestMapping(path="api/v1/file") @CrossOrigin(origins = "http://localhost:4200") public class filecontroller { @Autowired private final FileSystemStorageService filesService; public filecontroller(FileSystemStorageService filesService) { this.filesService = filesService; } @PostMapping("/upload") public ResponseEntity<responseMessage> uploadFiles(@RequestParam MultipartFile file){ String message = ""; try{ filesService.store(file); message = "File Uploaded successfully: "+file.getOriginalFilename(); return ResponseEntity.status(HttpStatus.OK).body(new responseMessage(message)); }catch (Exception e){ message = "Could not upload the file: "+file.getOriginalFilename() + "!"; return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(new responseMessage(message)); } } // other methods }
后端用户注册控制器
@RestController @RequestMapping(value = "api/v1/user") @CrossOrigin(origins = "http://localhost:4200") public class UserController { private final UserService userService; @Autowired public UserController(UserService userService) { this.userService = userService; } @PostMapping public void registerNewUser(@RequestBody UserClass user){ userService.addNewUser(user); } // other methods }
Angular文件上传组件
constructor(private route: Router, private files: PostFileServiceService) { } public main(){ this.username = localStorage.getItem('user_name'); } public onChangeFile(event: any){ this.formData = new FormData(); this.file = event.target.files[0]; if(this.file){ this.name = this.file.name; this.size = this.file.size; this.type = this.file.type; this.formData.append('fileSize', this.size); this.formData.append('fileType', this.type); this.userName = this.username; this.formData.append('userName', new Blob([JSON.stringify(this.userName)], {type: 'multipart/form-data'})); this.nameOfficial = this.name; if(this.nameOfficial.includes(" ")){ this.nameConcat = this.nameOfficial.split(" ").join(""); } this.formData.append('fileName', this.nameConcat ? this.nameConcat : this.nameOfficial); }else if(this.file==null){ return } } public onSubmit(){ this.requestSub = this.files.postFile(this.formData).subscribe((resp)=>{ if(resp==null){ this.subscribed = true; this.toCongrats('fileSuccessfull'); } }) } // other methods
Angular文件上传服务
public postFile(formData: FormData): Observable<any>{ const url = `http://localhost:8080/api/v1/file/`; return this.http.post(url+`/Upload`, formData); }
排查与解决方案
核心问题分析
- 请求URL大小写不匹配:后端文件上传端点为
/upload(小写u),但前端服务拼接的是/Upload(大写U),请求到不存在的端点后,Spring Boot返回的错误响应未携带CORS头,触发浏览器CORS报错。 - 前端未传递后端必填参数:后端方法仅接收
MultipartFile file参数,但前端FormData未添加file字段,反而传递了后端未定义的fileSize、fileType等参数,即使URL正确也会触发参数缺失错误。 - FormData参数处理错误:前端用
Blob包装userName属于冗余操作,会导致后端无法正常解析该参数(若后续需要)。
修复步骤
1. 修正前端请求URL大小写
修改Angular文件上传服务的URL,与后端端点保持一致:
public postFile(formData: FormData): Observable<any>{ const url = `http://localhost:8080/api/v1/file/upload`; // 改为小写upload return this.http.post(url, formData); }
2. 添加后端必填的file参数
修改Angular组件的onChangeFile方法,将选中的文件添加到FormData:
public onChangeFile(event: any){ this.formData = new FormData(); this.file = event.target.files[0]; if(this.file){ this.name = this.file.name; // 关键:添加后端需要的file参数 this.formData.append('file', this.file); // 直接传递字符串参数,无需Blob包装 this.userName = this.username; this.formData.append('userName', this.userName); this.nameConcat = this.name.includes(" ") ? this.name.split(" ").join("") : this.name; this.formData.append('fileName', this.nameConcat); } else { return; } }
3. (可选)全局统一CORS配置
若不想在每个控制器重复添加@CrossOrigin,可在Spring Boot中配置全局CORS规则,覆盖所有接口:
@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedOrigins("http://localhost:4200") .allowedMethods("GET", "POST", "PUT", "DELETE") .allowedHeaders("*") .allowCredentials(true); } }
配置完成后可移除所有控制器上的@CrossOrigin注解。
4. (可选)后端扩展参数接收
如果需要接收前端传递的userName、fileName等参数,修改后端方法的参数列表:
@PostMapping("/upload") public ResponseEntity<responseMessage> uploadFiles( @RequestParam MultipartFile file, @RequestParam String userName, @RequestParam String fileName) { // 业务逻辑实现 }
验证
- 重启Spring Boot后端与Angular前端。
- 选择文件提交,检查浏览器控制台是否仍有CORS错误。
- 查看后端日志,确认请求是否正确到达
/api/v1/file/upload端点,且参数可正常接收。
内容的提问来源于stack exchange,提问作者marcom966
相关产品推荐
相关产品推荐

