You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加@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);
}
排查与解决方案

核心问题分析

  1. 请求URL大小写不匹配:后端文件上传端点为/upload(小写u),但前端服务拼接的是/Upload(大写U),请求到不存在的端点后,Spring Boot返回的错误响应未携带CORS头,触发浏览器CORS报错。
  2. 前端未传递后端必填参数:后端方法仅接收MultipartFile file参数,但前端FormData未添加file字段,反而传递了后端未定义的fileSize、fileType等参数,即使URL正确也会触发参数缺失错误。
  3. 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) {
    // 业务逻辑实现
}

验证

  1. 重启Spring Boot后端与Angular前端。
  2. 选择文件提交,检查浏览器控制台是否仍有CORS错误。
  3. 查看后端日志,确认请求是否正确到达/api/v1/file/upload端点,且参数可正常接收。

内容的提问来源于stack exchange,提问作者marcom966

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 01:27:33