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

Angular调用Spring Boot导出Excel接口遇跨域问题排查

问题原因与解决方案

为什么会出现这个跨域错误?

  1. 后端response.reset()清空了CORS响应头
    Spring的@CrossOrigin注解会自动给响应加上Access-Control-Allow-Origin等跨域必需的头,但你在接口代码里调用了response.reset()——这个方法会把所有已设置的响应头(包括Spring刚加的CORS头)全部清空,导致前端请求时服务器返回的响应里没有跨域允许的标识,浏览器直接触发CORS拦截。

  2. Angular请求配置不匹配文件导出场景
    你当前用的get<void>是默认配置,没有指定响应类型为二进制流(blob),浏览器没法正确解析Excel文件的响应,同时这种配置也可能让跨域校验的逻辑出现异常。

怎么解决?

后端修复(两种方案选其一)

方案1:移除response.reset()

如果业务上不需要完全重置响应,直接删掉这一行就行,Spring通过@CrossOrigin添加的CORS头会保留,而且不影响Excel导出的响应设置:

@CrossOrigin
@GetMapping("/ticket/myTicketDownload")
public void myTicketDownload(HttpServletResponse response ) throws IOException {
    // 删掉response.reset()
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    response.setCharacterEncoding("utf-8");
    String day = DateUtils.localDateformat(LocalDate.now());
    String fileName = URLEncoder.encode("myTicket"+day, "UTF-8").replaceAll("\\+", "%20");
    response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
    TicketQueryDto ticketQueryDto = new TicketQueryDto();
    ticketQueryDto.setPkMyTicket("111");
    List<TicketVo> allTicketData = iTicketGeneralService.getMyTicketData(ticketQueryDto);
    EasyExcel.write(response.getOutputStream(), TicketVo.class).sheet(day).doWrite(allTicketData);
}

方案2:手动添加CORS头(必须保留response.reset()时用)

如果一定要重置响应,就在response.reset()之后手动补上跨域允许的头:

@CrossOrigin
@GetMapping("/ticket/myTicketDownload")
public void myTicketDownload(HttpServletResponse response ) throws IOException {
    response.reset();
    // 手动添加允许跨域的头,生产环境建议指定具体域名,不要用*
    response.setHeader("Access-Control-Allow-Origin", "http://localhost:4200");
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    response.setCharacterEncoding("utf-8");
    String day = DateUtils.localDateformat(LocalDate.now());
    String fileName = URLEncoder.encode("myTicket"+day, "UTF-8").replaceAll("\\+", "%20");
    response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
    TicketQueryDto ticketQueryDto = new TicketQueryDto();
    ticketQueryDto.setPkMyTicket("111");
    List<TicketVo> allTicketData = iTicketGeneralService.getMyTicketData(ticketQueryDto);
    EasyExcel.write(response.getOutputStream(), TicketVo.class).sheet(day).doWrite(allTicketData);
}

前端修复

修改Angular的请求,指定响应类型为blob,同时添加文件下载的逻辑(直接发get请求不会自动触发下载):

// Angular
exportMyTicket() {
  this.http.get(`http://localhost:8080/api/ticket/myTicketDownload`, { responseType: 'blob' })
    .subscribe((blob) => {
      // 创建临时下载链接
      const downloadUrl = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = downloadUrl;
      // 可以从响应头获取文件名,或者自定义
      link.download = `myTicket${new Date().toISOString().split('T')[0]}.xlsx`;
      document.body.appendChild(link);
      link.click();
      // 清理临时资源
      window.URL.revokeObjectURL(downloadUrl);
      document.body.removeChild(link);
    });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 05:55:20