Spring Boot 在[框架/库]中上传和下载文件时出现CORS问题

ss2ws0br  于 2023-06-05  发布在  Spring
关注(0)|答案(1)|浏览(205)

说明

我遇到了一个CORS(跨域资源共享)问题,特别是在我的angular-springboot 3应用程序中执行文件上传和下载操作时。CORS问题只发生在这些与文件相关的请求中,而其他API请求工作正常。

问题

尝试上传或下载文件时,我在浏览器控制台中收到以下错误消息:

Acess to XMLHttpRequest at 'http://localhost:8081/api/v1/download-excel' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

附加信息:

  • 我已经在后端控制器中为文件上传/下载端点设置了适当的@CrossOrigin注解。
  • 我已经验证了CORS问题是特定于文件上传和下载请求的,因为应用程序中的其他API请求不受影响。
  • 我尝试在前端www.example.com()方法中添加withCredentials: true选项http.post,但它没有解决CORS问题。
  • 服务器正确配置了CORS头,并允许来自前端源的请求。
    代码片段

前端:

uploadExcelFile(file: File): Observable<any> {
        return this.http.post(this.API_URL+'upload-excel', file);
    }

    downloadExcelFile(toDownload: any[]): Observable<HttpResponse<Blob>> {
        var idList: number[] = []
        toDownload.forEach((value)=> idList.push(value.id))
        const headers = new HttpHeaders({
            'Content-Type': 'application/octet-stream',
        });

        const params = new HttpParams().set('ids', idList.join(','));

        return this.http.post<Blob>(this.API_URL+'download-excel',params, {
            headers: headers,
            observe: 'response',
            responseType: 'blob' as 'json'
        }).pipe(
            catchError((error: any) => {
                console.error('Error occurred during file download:', error);
                throw error;
            })
        );
    }

后端:

@CrossOrigin(origins = "http://localhost:4200")
@RequestMapping(path = "/upload-excel", method = RequestMethod.POST)
public ResponseEntity<?> uploadExcelFile(@RequestParam("file") MultipartFile file) {
        ExcelUploader helper = new ExcelUploader();
        List<Entity> toAdd = helper.uploadFromExcel(file);
        navireRepository.saveAll(toAdd);
        return new ResponseEntity<>("File uploaded successfully", HttpStatus.OK);
}
    

@CrossOrigin(origins = "http://localhost:4200")
@RequestMapping(path = "/download-excel", method = RequestMethod.GET)
public ResponseEntity<byte[]> downloadExcelFile(@RequestBody List<Navire> toDownload) throws IOException {
        ExcelDownloader helper = new ExcelDownloader();
        List<Navire> toDownload = new ArrayList<>();
        for (Long id : ids) {
            toDownload.add(repository.getReferenceById(id));
        }

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.set("Access-Control-Allow-Origin", "*");
        headers.setContentDispositionFormData("attachment", "entity.xlsx");

        byte[] bytes = helper.downloadToExcel(toDownload);

        return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
    
}

她也是我的安全配置

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfiguration {

    private final JwtAuthenticationFilter jwtAuthFilter;
    private final AuthenticationProvider authenticationProvider;
    private final LogoutHandler logoutHandler;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf()
                .disable()
                .cors()
                .disable()
                .authorizeHttpRequests()
                .requestMatchers("/api/v1/**", "/swagger-ui/**", "/v3/api-docs/**")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authenticationProvider(authenticationProvider)
                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
                .logout()
                .logoutUrl("/api/v1/auth/logout")
                .addLogoutHandler(logoutHandler)
                .logoutSuccessHandler((request, response, authentication) -> SecurityContextHolder.clearContext())
        ;

        return http.build();
    }

}

我将非常感谢任何关于如何解决这个CORS问题的见解或建议,特别是与Sping Boot 3的文件上传和下载功能相关的问题。提前感谢您的帮助!

6ie5vjzr

6ie5vjzr1#

解决方案当我像这样添加全局cors配置时,一切都很顺利

@Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("http://localhost:4200");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }

相关问题