ASP.NET Core+Angular返回Blob生成无效PDF文件问题排查
问题原因及解决方案
你遇到的问题根源在于ASP.NET Core控制器错误地用Ok()包装了File()返回结果,导致后端返回的不是原始PDF字节流,而是序列化后的FileResult对象JSON。前端拿到这个JSON后直接转成Blob,相当于把JSON文本当作PDF内容保存,自然无法正常打开。
1. 修正后端控制器代码
直接返回FileResult,不要用Ok()包裹:
// 移除Ok()包装,直接返回File对象,可添加文件名参数方便前端下载 return File(await GetFileContents(args), "application/pdf", "result.pdf");
这样后端会直接输出PDF字节流,响应头的Content-Type会被正确设置为application/pdf,浏览器/前端能识别这是文件流而非JSON。
2. 修正前端HTTP请求配置
Angular默认会把响应解析为JSON,所以需要显式设置responseType: 'blob',确保拿到原始字节流:
// 在你的Service方法中添加responseType配置 getPDFFile(requestData: any): Observable<Blob> { return this.http.post(`/api/your-controller/action`, requestData, { responseType: 'blob' as 'json' // 类型断言用于兼容TypeScript类型检查 }); }
3. 简化前端下载逻辑
现在拿到的是Blob对象,直接传入saveAs即可:
this.myService.getPDFFile(requestData) .subscribe(blob => this.downloadFile(blob)); private downloadFile(blob: Blob) { saveAs(blob, 'result.pdf'); }
(可选)如果一定要用Base64方式(不推荐)
如果因为某些原因必须返回Base64编码的JSON,前端需要先解析JSON,再把Base64字符串转成Blob:
private downloadFile(data: any) { // 解码Base64字符串为字节数组 const byteCharacters = atob(data.fileContents); const byteNumbers = new Array(byteCharacters.length); for (let i = 0; i < byteCharacters.length; i++) { byteNumbers[i] = byteCharacters.charCodeAt(i); } const byteArray = new Uint8Array(byteNumbers); const blob = new Blob([byteArray], { type: 'application/pdf' }); saveAs(blob, 'result.pdf'); }
但这种方式会增加额外的编码解码开销,不如直接返回字节流高效。
内容的提问来源于stack exchange,提问作者Rohit
相关产品推荐
相关产品推荐

