Я сделал быстрое и грязное решение, вдохновленное этим другим постом о stackoverflow, и создал класс перехватчика http, который показывает, как можно выполнить анализ многочастных ответов.
Перехватчик возвращает первую часть 'application / json' в качестве тела ответа из составного ответа (multipart/mixed
, multipart/form-data
или multipart/related
).
Посредством карты дополнительные парсеры для других типов контента могут быть легко добавлены в класс.
Я поделюсь этим кодом, это может послужить вдохновением для других:
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
из ответа.
Вам понадобится собственный синтаксический анализатор или измените логику, если вы заинтересованы в возврате другого блока кода или если вы хотите объединить несколько блоков кода в окончательном ответе. Это потребует некоторой настройки кода.
ПРИМЕЧАНИЕ: Этот код является экспериментальным и ограниченным образом проверен, так что пока он не готов к работе, будьте осторожны при его использовании.