Spring Boot PNG下载接口在Angular中返回undefined的问题
Angular获取PNG接口返回undefined的解决办法
问题背景
Spring Boot后端提供PNG签名文件下载接口,Postman及浏览器网络面板可正常获取响应,但Angular订阅接口后始终得到undefined。
后端代码:
@GetMapping(value = "downloadsignature", produces = "image/png") public ResponseEntity downloadSignature(HttpServletRequest request) { var user = getUserOfRequest(); try { var resource = signFileStorage.loadFileAsResource(user.getSignatureImageFile()); return ResponseEntity.ok().contentType(MediaType.parseMediaType(request.getServletContext() .getMimeType(resource.getFile() .getAbsolutePath()))) .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"") .body(new InputStreamResource(resource.getInputStream())); } catch (Exception e) { logger.error(e.getMessage()); return ResponseEntity.badRequest().body("error.signature_cannot_read"); } }
原Angular服务代码:
public downloadSignature(): Observable<Blob> { return this.http.get<Blob>(`${this.getURL()}/downloadsignature`); }
原Angular组件调用代码:
ngOnInit(): void { this.profileService .downloadSignature() .pipe(catchError((error) => of(this.processError(error)))) .subscribe((item) => { console.log(item); }); }
问题原因
Angular HttpClient默认会将响应解析为JSON格式,而后端返回的是二进制PNG数据,解析失败后返回undefined。必须显式指定响应类型为blob才能正确处理二进制数据。
解决方案
1. 修正Angular服务代码
在get请求中添加responseType: 'blob'配置,明确告知HttpClient处理二进制Blob数据:
public downloadSignature(): Observable<Blob> { return this.http.get(`${this.getURL()}/downloadsignature`, { responseType: 'blob' // 关键配置:指定响应类型 }); }
2. 组件内正确处理响应
如果需要触发前端下载,可以在订阅后创建临时链接实现:
ngOnInit(): void { this.profileService .downloadSignature() .pipe(catchError((error) => { this.processError(error); return of(null); })) .subscribe((blob) => { if (blob) { console.log(blob); // 现在能正常获取Blob对象 // 触发文件下载 const downloadUrl = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = downloadUrl; link.download = 'signature.png'; // 设置下载文件名 document.body.appendChild(link); link.click(); // 清理资源 window.URL.revokeObjectURL(downloadUrl); document.body.removeChild(link); } }); }
3. 后端可选优化(规范写法)
后端已通过produces = "image/png"声明响应类型,可直接使用MediaType.IMAGE_PNG代替通过ServletContext获取MimeType,避免潜在问题:
@GetMapping(value = "downloadsignature", produces = "image/png") public ResponseEntity downloadSignature(HttpServletRequest request) { var user = getUserOfRequest(); try { var resource = signFileStorage.loadFileAsResource(user.getSignatureImageFile()); return ResponseEntity.ok() .contentType(MediaType.IMAGE_PNG) .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"") .body(new InputStreamResource(resource.getInputStream())); } catch (Exception e) { logger.error(e.getMessage()); return ResponseEntity.badRequest().body("error.signature_cannot_read"); } }
内容的提问来源于stack exchange,提问作者Ossama Nasser
相关产品推荐
相关产品推荐

