typescript HTTPClient POST 尝试解析非 JSON 响应

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/50826531/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 05:28:56  来源:igfitidea点击:

HTTPClient POST tries to parse a non-JSON response

angulartypescriptangular-httpclient

提问by Amy

I'm trying to make a request in Angular and I know that the HTTP response will not be in JSONbut in text. However, Angular seems to be expecting a JSON response since the error is the following:

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

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

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

As well as

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

解析http://localhost:9 时Http 失败...

This is the post method:

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

and the headers.

和标题。

private httpOptions = {

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

) };

I thought that responseType: 'text'would be enough to make Angular expect a non JSON response.

我认为这responseType: 'text'足以让 Angular 期待非 JSON 响应。

回答by Kirk Larkin

You've put responseType: 'text'in the wrong section of your httpOptions- It should sit outsideof headers, like so:

你已经把responseType: 'text'你的错误的部分httpOptions-它应该坐在外面headers,就像这样:

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

With what you had before, a request header of responseTypewas being sent to the server, rather than simply having an instruction to Angular to actually treat the response as text.

使用您之前所拥有的,请求标头responseType被发送到服务器,而不是简单地向 Angular 发出指令以实际将响应视为文本。

回答by Martin Eckleben

This code finally worked for me to xhr download a pdf file (Angular 6 / Laravel 5.6). The specialty for downloading a PDF file vs a text file was 'responseType': 'blob' as 'json'

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

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.')
     }
  )
}

I found the Solution through Kirk Larkins Answer (thank you a lot!) and a long angular github issue thread https://github.com/angular/angular/issues/18586#issuecomment-323216764

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

回答by Joe

If you just want to receive a plain text. You can set Http option without a header.

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

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

回答by Dilip Nannaware

Below given is the call from component which downloads the blob, compatible with IE and chrome:

下面给出的是来自下载 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;
    });

Below given is the service method which specifies the response type to be 'blob'

下面给出的是指定响应类型为“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);
}

Below is the code that makes httpClient call:

下面是调用 httpClient 的代码:

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