Angular接收Java返回CSV文件失败问题求助及解决反馈
解决CSV导出API返回正确数据但浏览器不触发下载且解析失败的问题
我遇到了一个CSV导出的问题:后端REST API返回状态码200且响应体数据正确,但浏览器无法触发文件下载,同时Angular端报错Error downloading the file.Http failure during parsing for myURL。
后端API代码(Java Spring)
ResponseEntity<Resource> exportCsv() throws IOException { InputStreamResource resource = new InputStreamResource(new FileInputStream(file)); HttpHeaders headers = new HttpHeaders(); headers.add("Content-disposition", "attachment; filename=sample.csv"); headers.add("Cache-Control", "no-cache, no-store, must-revalidate"); headers.add("Pragma", "no-cache"); headers.add("Expires", "0"); return ResponseEntity.ok() .headers(headers) .contentLength(file.length()) .contentType(MediaType.parseMediaType("text/csv")) .body(resource); }
Angular前端代码
Service中的请求方法
exportCsv( stickSearch: StickSearch ): Observable<any> { const headers = this.oAuthService.putTokenInHeaders(this.headers); let params = new HttpParams({encoder: new HttpURIEncoder()}); if (stickSearch.searchString() !== '') { params = params.append('search', stickSearch.searchString()) } return this.httpClient.get(this.exportCsvUrl + '/exportCsv', { responseType: 'text', params: params, headers }); }
组件中的调用与下载方法
this.stickService.exportCsv( this.stickSearch ) .subscribe( response => this.downloadFile(response), err => console.log('Error downloading the file.' + err.message )); downloadFile(data: Response) { const blob = new Blob([data], { type: 'text/csv' }); const url = window.URL.createObjectURL(blob); window.open(url); }
问题原因
报错的核心原因是Angular请求的responseType设置错误:后端返回的是文件流(二进制形式的CSV),但前端设置了responseType: 'text',Angular会尝试将二进制流解析为UTF-8字符串,这个解析过程会失败,从而抛出Http failure during parsing错误。另外,用window.open()触发下载的方式也不够可靠,容易被浏览器拦截,且没有明确指定文件名。
解决方法
1. 修改Angular请求的responseType为blob
将Service中的请求方法改为直接获取Blob类型的响应,避免解析错误:
exportCsv( stickSearch: StickSearch ): Observable<Blob> { const headers = this.oAuthService.putTokenInHeaders(this.headers); let params = new HttpParams({encoder: new HttpURIEncoder()}); if (stickSearch.searchString() !== '') { params = params.append('search', stickSearch.searchString()) } return this.httpClient.get(this.exportCsvUrl + '/exportCsv', { responseType: 'blob', // 改为blob类型,直接获取文件流 params: params, headers }); }
2. 优化下载方法,通过创建a标签触发下载
替换原有的downloadFile方法,使用更可靠的a标签方式,确保浏览器识别下载行为并指定文件名:
downloadFile(blob: Blob) { const url = window.URL.createObjectURL(blob); const downloadLink = document.createElement('a'); downloadLink.href = url; downloadLink.download = 'sample.csv'; // 与后端响应头指定的文件名保持一致 document.body.appendChild(downloadLink); downloadLink.click(); // 清理临时资源 window.URL.revokeObjectURL(url); document.body.removeChild(downloadLink); }
这样修改后,前端就能正确获取到文件流,通过a标签触发浏览器的下载行为,同时彻底解决了解析错误的问题。
内容的提问来源于stack exchange,提问作者a4fz067lu
相关产品推荐
相关产品推荐

