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

Angular 13接收后端BLOB转PDF时类型转换错误求助

问题根源

你的前端HttpClient.post参数顺序和配置完全错误,导致Angular默认将响应解析为JSON,这就是控制台报错的核心原因。同时后端请求Jasper Reports API时,也存在二进制数据获取的配置漏洞。


解决方案

1. 修复前端API调用代码

Angular HttpClient.post的参数顺序为:请求URL → 请求体 → 配置选项。你当前错误地将responseType作为请求体传递,params也未放在正确的配置位置。修正后的代码如下:

// 修正getReport方法
getReport(params: { acc_id: string; start_date: string; end_date: string; sage_num: string }) {
  // 参数放在请求体中(和后端接收逻辑对应),配置responseType为blob
  return this.http.post(`${environment.apiUrl}/api/accounts/report`, 
    { params },
    { responseType: 'blob' as 'json' } // as 'json'是TypeScript类型兼容处理技巧
  );
}

// 修正订阅逻辑
pdfExportBtn(e:any){
  const params={"acc_id":"18785","start_date":"2022/05/01, 00:00:00","end_date":"2022/06/01, 00:00:00","sage_num":"12341234"};

  this.getReport(params).subscribe((response: Blob) => {
    const downloadLink = document.createElement('a');
    downloadLink.target = '_self';
    const fileName = `${acc_name} Transaction Summary ${date1} to ${date2}.pdf`;
    const data = window.URL.createObjectURL(response);
    downloadLink.href = data;
    downloadLink.download = fileName;
    document.body.appendChild(downloadLink);
    downloadLink.click();
    // 清理URL对象避免内存泄漏
    window.URL.revokeObjectURL(data);
    document.body.removeChild(downloadLink);
  });
}

2. 修复后端Jasper API调用逻辑

后端使用request库获取报表时,必须设置encoding: null才能拿到二进制Buffer(否则response.body会被转成字符串,导致PDF损坏),同时要设置正确的响应头:

app.post('/api/accounts/report',(req,res)=>{
  const { acc_id, start_date, end_date, sage_num } = req.body.params;
  const request = require("request").defaults({ jar: true });

  // 登录Jasper Server
  request.post({
    url: jasper_login,
    qs: { j_username:jasper_usr, j_password:jasper_pwd }
  }, (err, resp, body) => {
    if(err) {
      console.error(err);
      return res.status(500).send('登录Jasper服务器失败');
    }
    // 请求报表时设置encoding: null获取二进制数据
    request.get({
      url: jasper_hst,
      encoding: null // 关键配置:确保返回Buffer而非字符串
    }, (error, response, body1) => {
      if (error || response.statusCode !== 200) {
        console.error(error || `报表请求失败,状态码:${response.statusCode}`);
        return res.status(500).send('生成报表失败');
      }
      // 设置正确的PDF响应头
      res.set({
        'Content-Type': 'application/pdf',
        'Content-Disposition': `inline; filename="report.pdf"`
      });
      res.send(body1); // body1是Buffer,直接发送即可
    })
  })
}); 

关键说明

  • 前端responseType必须在options对象中配置,TypeScript环境下需加as 'json'绕过类型校验。
  • 后端request.get必须添加encoding: null,否则二进制数据会被转成UTF-8字符串,导致PDF文件损坏。
  • 后端返回时明确设置Content-Type: application/pdf,让浏览器直接识别文件类型。

内容的提问来源于stack exchange,提问作者az-lt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 12:06:42