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

huangapple go评论78阅读模式
英文:

CORS issue during file upload and download in [framework/library]

问题

描述

在我的angular-springboot3应用程序中,当执行文件上传和下载操作时,我遇到了CORS(跨源资源共享)问题。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请求未受影响。
  • 我尝试在前端的http.post()方法中添加了withCredentials: true选项,但没有解决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) {
    // ... 省略部分代码 ...
    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 {
    // ... 省略部分代码 ...
    return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
}

安全配置

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfiguration {

    // ... 省略部分代码 ...
}

希望这些信息对你有所帮助,解决与Spring Boot 3相关的文件上传和下载功能的CORS问题。如果你有更多问题或需要进一步的协助,请随时提出。

英文:

Description

I'm encountering a CORS (Cross-Origin Resource Sharing) issue specifically when performing file upload and download operations in my angular-springboot3 application. The CORS problem occurs only with these file-related requests, while other API requests work fine.

Problem

When attempting to upload or download files, I receive the following error message in the browser console:

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

Additional Information:

  • I have already set the appropriate @CrossOrigin annotation in the backend controller for the file upload/download endpoints.
  • I have verified that the CORS issue is specific to file upload and download requests, as other API requests in the application are not affected.
  • I have tried adding the withCredentials: true option in the frontend http.post() method, but it did not resolve the CORS issue.
  • The server is properly configured with CORS headers and allows requests from the frontend origin.

Code snippets

Front End :

    uploadExcelFile(file: File): Observable&lt;any&gt; {
        return this.http.post(this.API_URL+&#39;upload-excel&#39;, file);
    }

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

        const params = new HttpParams().set(&#39;ids&#39;, idList.join(&#39;,&#39;));

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

Back end:

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

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

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

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

        return new ResponseEntity&lt;&gt;(bytes, headers, HttpStatus.OK);
    
}

hers my security configuration too

@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(&quot;/api/v1/**&quot;, &quot;/swagger-ui/**&quot;, &quot;/v3/api-docs/**&quot;)
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authenticationProvider(authenticationProvider)
                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
                .logout()
                .logoutUrl(&quot;/api/v1/auth/logout&quot;)
                .addLogoutHandler(logoutHandler)
                .logoutSuccessHandler((request, response, authentication) -&gt; SecurityContextHolder.clearContext())
        ;

        return http.build();
    }


}

I would greatly appreciate any insights or suggestions on how to resolve this CORS issue specifically related to file upload and download feature with Spring boot 3. Thank you in advance for your help!

答案1

得分: 0

解决方案
当我添加了一个全局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;
    }
英文:

Solution
It all went smoothly when I added a global cors configuration like so

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

huangapple
  • 本文由 发表于 2023年5月29日 01:28:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76352729.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定