HTTPClient POST 尝试解析 non-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方法:
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)
)
);
和 headers.
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
的 之外 ,如下所示:
private httpOptions = {
headers: new HttpHeaders({
'Accept': 'text/html, application/xhtml+xml, */*',
'Content-Type': 'application/x-www-form-urlencoded'
}),
responseType: 'text'
};
根据您之前的情况,responseType
的请求 header 被发送到服务器,而不是简单地向 Angular 发送指令以实际将响应视为文本.
这段代码最终对我有用 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.')
}
)
}
我通过 Kirk Larkins Answer(非常感谢!)和一个很长的 angular github issue thread https://github.com/angular/angular/issues/18586#issuecomment-323216764
找到了解决方案
下面给出的是下载 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;
如果您只想接收纯文本。您可以在没有 header.
的情况下设置 Http 选项
this.http.get("http://localhost:3000/login",{responseType: 'text'})
.subscribe((result)=>console.log(result))
我在 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 结果(如休息 api):
HttpClient.get(url) // returns Observable Json formatted
如果需要文本或原始 html:
HttpClient.get(url, {responseType:'text'}) // returns a string Observable
如果 return 类型是意外的(您也会得到 header 类型,以便您可以正确解析数据):
HttpClient.get(url, {observe:response}) //returns Observable<HttpResponse <T>>
默认情况下,Angular 将响应类型设置为 JSON。
要覆盖它,您可以使用 headers 并将 responseType
设置为 'text'
或者一个简单的方法是这样的
this.http.get(url, {responseType: 'text'})
使用 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(...
我正在尝试在 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方法:
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)
)
);
和 headers.
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
的 之外 ,如下所示:
private httpOptions = {
headers: new HttpHeaders({
'Accept': 'text/html, application/xhtml+xml, */*',
'Content-Type': 'application/x-www-form-urlencoded'
}),
responseType: 'text'
};
根据您之前的情况,responseType
的请求 header 被发送到服务器,而不是简单地向 Angular 发送指令以实际将响应视为文本.
这段代码最终对我有用 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.')
}
)
}
我通过 Kirk Larkins Answer(非常感谢!)和一个很长的 angular github issue thread https://github.com/angular/angular/issues/18586#issuecomment-323216764
找到了解决方案下面给出的是下载 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;
如果您只想接收纯文本。您可以在没有 header.
的情况下设置 Http 选项this.http.get("http://localhost:3000/login",{responseType: 'text'})
.subscribe((result)=>console.log(result))
我在 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 结果(如休息 api):
HttpClient.get(url) // returns Observable Json formatted
如果需要文本或原始 html:
HttpClient.get(url, {responseType:'text'}) // returns a string Observable
如果 return 类型是意外的(您也会得到 header 类型,以便您可以正确解析数据):
HttpClient.get(url, {observe:response}) //returns Observable<HttpResponse <T>>
默认情况下,Angular 将响应类型设置为 JSON。
要覆盖它,您可以使用 headers 并将 responseType
设置为 'text'
或者一个简单的方法是这样的
this.http.get(url, {responseType: 'text'})
使用 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(...