在Angular中处理多部分响应主体 [英] Handling a multipart Response body in Angular

查看:102
本文介绍了在Angular中处理多部分响应主体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Angular中收到了一个多部分响应正文,但应用程序未正确处理响应.事实证明,Angular中的HttpClient无法正确解析多部分响应主体(请参阅GitHub上的此问题).

I receive a multipart response body in Angular but the application is not handling the response correctly. It turns out the HttpClient in Angular is not able to parse multipart response bodies correctly (see this issue on GitHub).

HttpClient 只是返回 HttpResponse 对象主体内部的原始多部分响应,而我想拥有 application/json 块从我的 HttpResponse 对象内部可访问的多部分响应中.

The HttpClient simply returns the raw multipart response inside the body of the HttpResponse object while I would like to have the application/json block from the multipart response accessible inside my HttpResponse object.

如何在Angular中正确处理多部分响应?

How can I handle multipart response inside Angular correctly?

推荐答案

我在这则其他帖子的启发下,提出了一个快速而肮脏的解决方案在stackoverflow上创建了一个HTTP拦截器类,该类显示了如何解析多部分响应.拦截器从多部分响应( multipart/mixed multipart/form-data multipart/相关).通过映射,可以轻松地将其他内容类型的其他解析器添加到类中.

I made a quick and dirty solution heavily inspired by this other post on stackoverflow and created an http interceptor class that shows how parsing multipart responses can be done. The interceptor returns the the first 'application/json' part as the response body from a multipart response (multipart/mixed, multipart/form-data or multipart/related). Through a map additional parsers for other content types can be easily added to the class.

我将在此处分享此代码,这可能会给其他人带来启发:

I will share this code here it might be an inspiration others:

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 块.

The code reads the boundary from the Content-Type response header and splits the response body in blocks using this boundary. Then it tries to parse each part and returns the first successfully parsed application/json block from the response.

如果您有兴趣返回另一个代码块,或者想要在最终响应中组合多个代码块,则需要使用自己的解析器或更改逻辑.这需要对代码进行一些自定义.

You would need your own parser or change the logic in case you are interested in returning another code block or in case you want to combine several code blocks in the final response. This would need some customization of the code.

注意:该代码是实验性的,经过严格测试,尚未投入生产,使用时请务必小心.

NOTE: This code is experimental and limited tested so far from production ready, be careful when using it.

这篇关于在Angular中处理多部分响应主体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆