关于angular:HTTPClient POST尝试解析非JSON响应

HTTPClient POST tries to parse a non-JSON response

我正在尝试在Angular中发出请求,并且我知道HTTP响应将不是JSON形式而是文本形式。 但是,Angular似乎期望JSON响应,因为错误如下:

SyntaxError: Unexpected token < in JSON at position 0 at JSON.parse () at XMLHttpRequest.c

以及

Http failure during parsing for http://localhost:9...

这是post方法:

1
2
3
4
5
6
7
return this.http.post(this.loginUrl, this.createLoginFormData(username, password), this.httpOptions)
  .pipe(
    tap( // Log the result or error
      data => console.log(data);
      error => console.log(error)
    )
  );

和标题。

1
2
3
4
5
6
7
8
9
private httpOptions = {

  headers: new HttpHeaders({
    'Accept': 'text/html, application/xhtml+xml, */*',
    'Content-Type': 'application/x-www-form-urlencoded',
    responseType: 'text'
  },

) };

我认为responseType: 'text'足以使Angular期待一个非JSON响应。


您已将responseType: 'text'放在httpOptions的错误部分中-它应位于headers之外,如下所示:

1
2
3
4
5
6
7
private httpOptions = {
  headers: new HttpHeaders({
    'Accept': 'text/html, application/xhtml+xml, */*',
    'Content-Type': 'application/x-www-form-urlencoded'
  }),
  responseType: 'text'
};

像以前一样,responseType的请求标头被发送到服务器,而不是简单地向Angular发出指令以将响应实际视为文本。


这段代码终于对我有用,可以xhr下载pdf文件(Angular 6 / Laravel 5.6)。
下载PDF文件与文本文件的专业是'responseType': 'blob' as 'json'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
showPdf(filename: String){
  this.restService.downloadFile(
     'protected/getpdf',
     {'filename': filename}
  )
}

//method from restService
public downloadFile(endpoint:String, postData:Object){

  var restService = this

  var HTTPOptions = {
     headers: new HttpHeaders({
        'Accept':'application/pdf'
     }),
     'responseType': 'blob' as 'json'
  }

  this.http.post(this.baseurl+endpoint,postData,HTTPOptions )
  .subscribe(
     res => {
        console.log(res) //do something with the blob
     },
     error => {
        console.error('download error:', error)
     },
     () => {
        console.log('Completed file download.')
     }
  )
}

我通过Kirk Larkins Answer(非常感谢!)和长角github问题线程https://github.com/angular/angular/issues/18586#issuecomment-323216764找到了解决方案


如果您只想接收纯文本。您可以设置不带标题的Http选项。

1
2
this.http.get("http://localhost:3000/login",{responseType: 'text'})
.subscribe((result)=>console.log(result))

下面给出的是来自下载blob的组件的调用,该组件与IE和chrome兼容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    this.subscribe(this.reportService.downloadReport(this.reportRequest, this.password), response => {
        let blob = new Blob([response], { type: 'application/zip' });
        let fileUrl = window.URL.createObjectURL(blob);
        if (window.navigator.msSaveOrOpenBlob) {
            window.navigator.msSaveOrOpenBlob(blob, fileUrl.split(':')[1] + '.zip');
        } else {
            this.reportDownloadName = fileUrl;
            window.open(fileUrl);
        }
        this.spinner = false;
        this.changeDetectorRef.markForCheck();
    },
    error => {
        this.spinner = false;
    });

下面给出的服务方法将响应类型指定为" blob"

1
2
3
4
5
downloadReport(reportRequest: ReportRequest, password: string): Observable {
    let servicePath = `${basePath}/request/password/${password}`;
    this.httpOptions.responseType = 'blob';
    return this.endpointService.post(endpoint, servicePath, reportRequest, this.httpOptions);
}

以下是进行httpClient调用的代码:

1
2
3
4
    //Make the service call:
    let obs = this.httpClient.request(method, url, options);
    //Return the observable:
    return obs;

在有角度的更新之后,由于http客户端被更新为将响应解析为JSON,我遇到了同样的问题,当响应不包含有效的json(即文本或原始html)时失败。

为了避免自动进行json解析,请在get或post调用中将标头" responseType"添加为参数:

1
2
3
4
5
6
this.http.get(template,{responseType:'text'})
  .subscribe(result => {

    // result contains the"treated as text content"

    });

一般来说:
如果期望得到Json结果(例如在rest api中):

1
 HttpClient.get(url) // returns Observable Json formatted

如果需要文本或原始html:

1
HttpClient.get(url, {responseType:'text'}) // returns a string Observable

如果返回类型是意外的(您还将获得标头,以便可以正确解析数据):

1
HttpClient.get(url, {observe:response}) //returns Observable<HttpResponse < T >>