React向SpringBoot+MongoDB发POST请求时遇415及CORS错误
解决方案:React图片上传到SpringBoot后端的CORS与415/403错误处理
错误原因分析
- 403 + CORS错误:SpringBoot端未正确配置跨域规则,或SpringSecurity拦截了跨域预检(OPTIONS)请求及上传接口,导致权限拒绝。
- 415 + CORS错误:后端接口参数接收方式错误(如误用
@RequestBody处理multipart/form-data),或前端手动设置Content-Type导致请求边界(boundary)丢失,后端无法解析表单数据;同时跨域配置仍存在漏洞。 no-cors模式无效:该模式仅限制浏览器对响应的读取,无法解决后端的跨域配置问题,反而会阻碍调试。
分步解决
1. 修正前端请求代码(React)
不要手动设置Content-Type,FormData会自动生成带正确boundary的multipart/form-data请求头;确保请求携带必要凭证(如需要):
const handleUpload = async (e) => { e.preventDefault(); const formData = new FormData(); // 追加文件与其他表单字段 formData.append('uploadFile', document.getElementById('fileInput').files[0]); formData.append('title', '测试图片'); try { const res = await fetch('http://localhost:8080/api/upload', { method: 'POST', credentials: 'include', // 若后端需要Cookie则开启 body: formData // 无需手动设置Content-Type,浏览器自动处理 }); const result = await res.json(); console.log('上传成功:', result); } catch (err) { console.error('上传失败:', err); } };
2. 修正后端接口与跨域配置(SpringBoot)
方式一:接口级跨域配置
直接在上传接口上添加@CrossOrigin,明确允许跨域来源、请求方法与头部:
@RestController @RequestMapping("/api") public class UploadController { @PostMapping("/upload") @CrossOrigin(origins = "http://localhost:3000", // React项目地址 allowedHeaders = "*", methods = {RequestMethod.POST, RequestMethod.OPTIONS}) public ResponseEntity<String> upload( @RequestPart("uploadFile") MultipartFile file, @RequestPart("title") String title) { // 处理MongoDB存储逻辑(如使用GridFS存储文件) return ResponseEntity.ok("文件上传成功:" + file.getOriginalFilename()); } }
注意:必须用
@RequestPart接收文件与表单字段,不能用@RequestBody(后者仅处理JSON格式数据)。
方式二:全局跨域配置
若多个接口需要跨域,推荐全局配置:
@Configuration public class GlobalCorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:3000") .allowedMethods("GET", "POST", "OPTIONS", "DELETE", "PUT") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); // 预检请求缓存时长 } }
3. SpringSecurity兼容配置(若使用)
如果项目集成了SpringSecurity,需放行OPTIONS预检请求与上传接口,同时启用CORS:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.cors() // 启用CORS配置 .and() .csrf().disable() // 若无需CSRF保护可关闭,或配置CSRF令牌 .authorizeRequests() .antMatchers("/api/upload").permitAll() // 放行上传接口 .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 放行预检请求 .anyRequest().authenticated(); } // 注入全局CORS配置 @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(Arrays.asList("http://localhost:3000")); config.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS")); config.setAllowedHeaders(Arrays.asList("*")); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; } }
4. 验证Multipart解析配置
SpringBoot默认已自动配置MultipartResolver,无需额外配置;若自定义了该Bean,确保配置正确:
@Bean public MultipartResolver multipartResolver() { CommonsMultipartResolver resolver = new CommonsMultipartResolver(); resolver.setMaxUploadSize(10485760); // 设置最大上传大小(10MB) return resolver; }
内容的提问来源于stack exchange,提问作者devops777
相关产品推荐
相关产品推荐

