簡體   English   中英

在Angular中處理多部分響應主體

[英]Handling a multipart Response body in Angular

我在Angular中收到一個包含多個部分的響應正文,但應用程序未正確處理響應。 事實證明,Angular中的HttpClient無法正確解析多部分響應主體(請參閱GitHub上的此問題 )。

HttpClient只是在HttpResponse對象的主體內返回原始的multipart響應,而我希望在我的HttpResponse對象內可以訪問來自multipart響應的application/json塊。

如何正確處理Angular中的多部分響應?

我從stackoverflow上的一篇文章中獲得了極大的啟發,提出了一個快速而骯臟的解決方案,並創建了一個HTTP攔截器類,該類顯示了如何解析多部分響應。 攔截器從多部分響應( multipart/mixedmultipart/form-datamultipart/related )返回第一個“ application / json”部分作為響應主體。 通過映射,可以輕松地將其他內容類型的其他解析器添加到類中。

我將在此處分享此代碼,這可能會給其他人帶來啟發:

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

@Injectable({
  providedIn: 'root',
})

export class MultipartInterceptService implements HttpInterceptor {

  private parserMap = {
    'application/json': JSON.parse,
  };

  private parseMultipart(multipart: string, boundary: string): any {
    const dataArray: string[] = multipart.split(`--${boundary}`);
    dataArray.shift();
    dataArray.forEach((dataBlock) => {
      const rows = dataBlock.split(/\r?\n/).splice(1, 4);
      if (rows.length < 1) {
        return;
      }
      const headers = rows.splice(0, 2);
      const body = rows.join('');
      if (headers.length > 1) {
        const pattern = /Content-Type: ([a-z\/+]+)/g;
        const match = pattern.exec(headers[0]);
        if (match === null) {
          throw Error('Unable to find Content-Type header value');
        }
        const contentType = match[1];
        if (this.parserMap.hasOwnProperty(contentType) === true) {
          return this.parserMap[contentType](body);
        }
      }
    });
    return false;
  }

  private parseResponse(response: HttpResponse<any>): HttpResponse<any> {
    const contentTypeHeaderValue = response.headers.get('Content-Type');
    const body = response.body;
    const contentTypeArray = contentTypeHeaderValue.split(';');
    const contentType = contentTypeArray[0];
    switch (contentType) {
      case 'multipart/related':
      case 'multipart/mixed':
      case 'multipart/form-data':
        const boundary = contentTypeArray[1].split('boundary=')[1];
        const parsed = this.parseMultipart(body, boundary);
        if (parsed === false) {
          throw Error('Unable to parse multipart response');
        }
        return response.clone({ body: parsed });
      default:
        return response;
    }
  }

  // intercept request and add parse custom response
  public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request)
      .pipe(
        map((response: HttpResponse<any>) => {
          if (response instanceof HttpResponse) {
            return this.parseResponse(response);
          }
        }),
      );
  }
}

該代碼從Content-Type響應標頭讀取邊界,並使用該邊界將響應主體拆分為多個塊。 然后,它嘗試解析每個部分,並從響應中返回第一個成功解析的application/json塊。

如果您有興趣返回另一個代碼塊,或者想要在最終響應中組合多個代碼塊,則需要使用自己的解析器或更改邏輯。 這將需要對代碼進行一些自定義。

注意:此代碼是實驗性的,經過嚴格測試,尚未投入生產,請謹慎使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM