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

Angular 5中如何处理带Blob响应与JSON错误的HTTP GET请求

处理Angular 5下载请求中的JSON格式错误

这个问题我之前做Angular文件下载时也碰到过——当你把responseType设为blob后,不管后端返回的是正常文件还是JSON格式的错误响应,Angular都会把响应体包装成Blob,没法直接解析成JSON来获取错误信息。下面给你几种实用的解决方式:

1. 在请求调用处直接处理错误

最简单的方式是在subscribe的错误回调里,把错误的Blob转换成文本再解析成JSON:

public onDownload() {
  this.downloadService.executeDownload(this.id).subscribe(
    res => {
      saveAs(res, 'file.pdf');
    },
    (error: HttpErrorResponse) => {
      // 后端返回的错误体是Blob类型,需要先读取成文本
      if (error.error instanceof Blob) {
        const reader = new FileReader();
        // 读取完成后解析JSON
        reader.onload = () => {
          try {
            const errorDetails = JSON.parse(reader.result as string);
            console.error('下载失败:', errorDetails);
            // 这里可以给用户展示具体错误,比如弹窗提示
            alert(`下载出错:${errorDetails.message || '未知错误'}`);
          } catch (e) {
            // 如果解析失败,说明不是JSON格式的错误(比如二进制文件损坏)
            alert('下载文件时发生未知错误');
          }
        };
        reader.readAsText(error.error);
      } else {
        // 非Blob类型的错误,直接处理
        console.error('下载失败:', error.error);
        alert(`下载出错:${error.error?.message || error.message}`);
      }
    }
  );
}

2. 在服务层封装错误处理逻辑

如果多个地方都有下载需求,可以把错误处理逻辑封装到服务里,让调用更简洁:

首先修改服务中的executeDownload方法:

import { catchError } from 'rxjs/operators';
import { Observable, throwError } from 'rxjs';
import { HttpErrorResponse } from '@angular/common/http';

public executeDownload(id: string): Observable<Blob> {
  return this.http.get(this.replaceUrl('app/download', id), {responseType: 'blob'}).pipe(
    catchError((error: HttpErrorResponse) => {
      return new Observable<never>(observer => {
        if (error.error instanceof Blob) {
          const reader = new FileReader();
          reader.onload = () => {
            try {
              const errorObj = JSON.parse(reader.result as string);
              observer.error(errorObj);
            } catch (e) {
              observer.error('无法解析错误信息,请稍后重试');
            }
          };
          reader.onerror = () => observer.error('读取错误信息失败');
          reader.readAsText(error.error);
        } else {
          observer.error(error.error || error.message);
        }
      });
    })
  );
}

然后调用的时候就可以直接处理解析好的错误:

public onDownload() {
  this.downloadService.executeDownload(this.id).subscribe(
    res => saveAs(res, 'file.pdf'),
    error => {
      console.error('下载失败:', error);
      alert(`下载出错:${error.message || '未知错误'}`);
    }
  );
}

3. 全局拦截器统一处理(推荐)

如果你的应用中有很多下载请求,用全局HTTP拦截器来统一处理这种Blob错误会更高效,不用每个请求都写重复代码:

首先创建一个拦截器:

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

@Injectable()
export class DownloadErrorInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // 只处理responseType为blob的请求
    if (req.responseType === 'blob') {
      return next.handle(req).pipe(
        catchError((error: HttpErrorResponse) => {
          return new Observable<never>(observer => {
            if (error.error instanceof Blob) {
              const reader = new FileReader();
              reader.onload = () => {
                try {
                  const errorJson = JSON.parse(reader.result as string);
                  observer.error(errorJson);
                } catch (e) {
                  observer.error('下载文件时发生错误');
                }
              };
              reader.readAsText(error.error);
            } else {
              observer.error(error.error || error.message);
            }
          });
        })
      );
    }
    // 非Blob请求直接放行
    return next.handle(req);
  }
}

然后在AppModule中注册这个拦截器:

import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { DownloadErrorInterceptor } from './download-error.interceptor';

@NgModule({
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: DownloadErrorInterceptor,
      multi: true // 允许多个拦截器
    }
  ]
})
export class AppModule { }

这样所有设置了responseType: 'blob'的请求,遇到JSON错误时都会自动解析成JSON对象抛出,调用处只需要正常处理错误即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:14:19