HTTPClient POST пытается проанализировать ответ не-JSON

Я пытаюсь сделать запрос в Angular, и я знаю, что ответ HTTP будет не в JSON, а в текстовом формате. Тем не менее, похоже, что Angular ожидает ответа JSON, поскольку ошибка следующая:

SyntaxError: неожиданный токен <в JSON в позиции 0 в JSON.parse() в XMLHttpRequest.c

Так же как

Ошибка http во время синтаксического анализа для http://localhost: 9...

Это метод сообщения:

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.

Ответ 1

Вы положили 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, чтобы фактически обрабатывать ответ как текст.

Ответ 2

Этот код, наконец, сработал для меня, чтобы загрузить 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.')
     }
  )
}

Я нашел решение с помощью ответа Кирка Ларкинса (большое спасибо!) и длинной angular проблемы с github. https://github.com/angular/angular/issues/18586#issuecomment-323216764

Ответ 3

Если вы просто хотите получить простой текст. Вы можете установить опцию Http без заголовка.

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

Ответ 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;