【问题标题】:HTTPClient POST tries to parse a non-JSON responseHTTPClient POST 尝试解析非 JSON 响应
【发布时间】:2018-11-22 09:41:56
【问题描述】:

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

SyntaxError: JSON.parse 中位置 0 的 JSON 中的意外标记

还有

解析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 响应。

【问题讨论】:

  • 您可以将回复作为示例发布吗?
  • 嘿,艾米,你想把它转换成 JSON 吗?你能显示完整的代码吗?还有你从 API 得到的响应?
  • “我认为 responseType: 'text' 足以让 Angular 期待非 JSON 响应。” - 如果你在正确的位置指定它开头……这不是 HTTP 标头之一!
  • Angular 7 HttpClient - 如果您来自 Google 搜索,如果您尝试获取字符串并且没有自动 JSON 解析假设,则此链接的问题和评论可能与您相关。 stackoverflow.com/a/57084925/2080879

标签: angular typescript angular-httpclient


【解决方案1】:

默认情况下,Angular 将响应类型设置为 JSON。

要覆盖它,您可以使用标题并将responseType 设置为'text' 或者一个简单的方法是这样的

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

【讨论】:

    【解决方案2】:

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

    为避免自动 json 解析,在 get 或 post 调用中添加标头“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>> 
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 是的,它应该可以工作,但看起来那里有一个错误,你可以通过使用 'text' as 'json' 来修复它
      【解决方案4】:

      下面是下载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;
      

      【讨论】:

        【解决方案5】:

        这段代码终于帮我下载了一个 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.')
             }
          )
        }
        

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

        【讨论】:

        • 有一个 json 请求,但响应是一个 xml,角度期望如果你有一个 json 请求,你应该有一个 json 的响应。如果你不这样做,它就会抛出。可能是服务器端的良好做法。我使用了你的技巧'test/xml' as 'json' 来避免在请求状态 == 200 时出错,但如果状态错误仍然会出错。
        【解决方案6】:

        您将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 将响应实际视为文本。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-03-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多