typescript HTTPClient POST尝试解析非JSON响应

uemypmqf  于 11个月前  发布在  TypeScript
关注(0)|答案(8)|浏览(124)

我尝试在Angular中发出请求,我知道HTTP响应将不是JSON而是文本。然而,Angular似乎期待JSON响应,因为错误如下:
语法错误:JSON中的位置0处的意外标记<.parse()at XMLHttpRequest. c
以及
解析http://localhost:9时HTTP失败...
这就是post方法:

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)
    )
  );

字符串
和标题。

private httpOptions = {

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

) };


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

nmpmafwu

nmpmafwu1#

你把responseType: 'text'放在了httpOptions的错误部分-它应该位于headers的 * 外部 *,如下所示:

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

字符串
与之前一样,responseType的请求头被发送到服务器,而不是简单地向Angular发送一个指令,实际上将响应视为文本。

pn9klfpd

pn9klfpd2#

这段代码最终让我可以xhr下载一个pdf文件(Angular 6 / Laravel 5.6)。下载PDF文件与文本文件的专长是'responseType': 'blob' as 'json'

showPdf(filename: String){
  this.restService.downloadFile(
     'protected/getpdf',
     {'filename': filename}
  )
}

字符串
restService.ts:

public downloadFile(endpoint:String, postData:Object){

  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(非常感谢!)和一个长Angular 的github问题线程https://github.com/angular/angular/issues/18586#issuecomment-323216764找到了解决方案

toe95027

toe950273#

如果你只想接收一个纯文本。你可以设置没有头的Http选项。

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

字符串

kse8i1jr

kse8i1jr4#

默认情况下,Angular将响应类型设置为JSON。
要覆盖它,可以使用头文件并将responseType设置为'text',或者使用一个简单的方法,如下所示

this.http.get(url, {responseType: 'text'})

字符串

yvfmudvl

yvfmudvl5#

使用Angular 13:
对于文本回复:

var options = {
     headers: new HttpHeaders({
        'Accept':'text/plain'
     }),
     'responseType': 'text' as 'json'
  }

  this.http.post(url,null,options).subscribe(...

字符串
对于二进制文件响应:

var options = {
     headers: new HttpHeaders({
        'Accept':'image/jpeg' //or 'Accept':'application/pdf' .. etc
     }),
     'responseType': 'blob' as 'json'
  }

  this.http.post<Blob>(url,null,options).subscribe(...

6fe3ivhb

6fe3ivhb6#

下面给出的是从下载blob的组件调用,与IE和Chrome兼容:

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'

downloadReport(reportRequest: ReportRequest, password: string): Observable<any> {
    let servicePath = `${basePath}/request/password/${password}`;
    this.httpOptions.responseType = 'blob';
    return this.endpointService.post(endpoint, servicePath, reportRequest, this.httpOptions);
}


下面是httpClient调用的代码:

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

piah890a

piah890a7#

在一次Angular 更新后,我遇到了同样的问题,因为http客户端被更新为将响应解析为JSON,当响应不包含有效的JSON(即文本或原始html)时失败。
为了避免自动json解析,在get或post调用中添加header“responseType”作为参数:

this.http.get(template,{responseType:'text'})
  .subscribe(result => {

    // result contains the "treated as text content"

    });

字符串

**一般情况下:**如果期望一个JSON结果(如在rest API中):

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


如果需要文本或原始html:

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


如果返回类型是意外的(你也会得到头,这样你就可以正确地解析你的数据):

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

8nuwlpux

8nuwlpux8#

因为我的API有时返回纯文本/布尔值/数字,有时返回JSON对象,所以当httpclient试图解析JSON响应(如果是文本)时,我得到了这个错误。
我最终将 responsetype 设置为始终为文本,这样httpclient就不会试图在内部将其解析为JSON,从而导致此错误,然后我自己将其解析为json。try catch 很重要,因为我们还希望布尔值/数字被解析,否则我们将其作为文本获取.

return this.httpClient.get(`${environment.apiUrl}${url}`, { responseType: "text" }).pipe(map(r => { try { r = JSON.parse(r); } catch { } return r; }));

字符串

相关问题