如何在Angular 8中下载Excel文件作为API响应

时间:2019-10-11 06:57:54

标签: excel angular api post

我有一个API,该API返回excel文档作为响应。该请求将是一个简单的json。

我搜索了google并找到了一些代码库来下载该文件,并在我的应用程序中使用了它,但是我遇到了一些错误,无法找到解决方案。下面是我的代码库。

component.ts

import rxjs/Rx;

details = {id: 75,name: "some name"}

this.nameService.getData(this.details).subscribe(response => {
this.downloadFile(response);
})

downloadFile(data: Response) {
  const blob = new Blob([data], { type: '.xlsx' });
  const url= window.URL.createObjectURL(blob);
  window.open(url);
}

nameService.ts

getData(postData) {
  return this.httpService.post('https://localhost:8080/getFile/', postData);
}

httpService.ts

constructor(private http: HttpClient)
post(apiEndpoint: string, request: any) :Observable<any> {
 return this.http.post<any>(apiEndpoint,request);
}

使用上述代码库,我遇到以下两个错误,并且文件未下载。

  1. 获取错误:
  

在创建Blob时“类型响应不能分配给Blobpart类型”(const blob = new Blob([data],{type:'.xlsx'});)

  1. 如果我将数据更改为任何(downloadFile(data:any)),则上述错误(1)将消失,但我收到的httperror响应为“语法错误:json中位置0的意外令牌P在josn中。解析”

如果有人找到上述问题的解决方案,请提供帮助。

6 个答案:

答案 0 :(得分:2)

添加标题{ responseType: 'blob'}

赞:

this.http.post<any>(apiEndpoint,request,{ responseType: 'blob'} )

答案 1 :(得分:2)

在请求中设置响应头 { responseType: 'blob'}

要下载excel,请使用以下功能。

response - api 响应, 文件名- excel 名称

downloadExcel(response, fileName) {
    // Doing it this way allows you to name the file
    var link = document.createElement('a');
    link.href = window.URL.createObjectURL(res);
    link.download = fileName;
    link.click();
  }

答案 2 :(得分:1)

  1. 您需要在请求中设置响应头{ responseType: 'blob'}

  2. 创建blob文件时,您需要传递正确的MIME类型。 (例如 application / octet-stream application / vnd.openxmlformats-officedocument.spreadsheetml.sheet )。

component.ts

downloadFile(data: Response) {
  const blob = new Blob([data], { type: 'application/octet-stream' });
  const url= window.URL.createObjectURL(blob);
  window.open(url);
}

答案 3 :(得分:0)

要下载文件,请使用以下代码

downloadFile(data: Response) {
  const blob = new Blob([data], { type: 'application/octet-stream' });
  fs.saveAs(blob, fileName + '.xlsx');
}

答案 4 :(得分:0)

虽然大多数答案在这里使用{ responseType: 'blob'}都可以,但是我建议使用responseType: 'arraybuffer'代替blobobserve: 'response'。然后您的呼叫将如下所示:

this.httpClient.get(resource, {
  headers: this.httpHeaders, // Any custom client side headers like Authorization
  observe: 'response',
  responseType: 'arraybuffer'
});

这样做的好处有两个:

  1. Arraybuffer是通用的字节流,可以使用blobarraybuffer,并使用Content-Type来创建Blob对象
  2. observe: 'response'还将在解析的响应中包含您在服务器上设置的响应标头。

我使用此方法将arraybuffer的文件名和MIME类型放在Content-DispositionContent-Type响应标头中,然后在客户端使用通用下载服务。

此外,我建议使用File对象,而不是仅使用Blob,这样可以灵活地给它提供文件名,如下所示:

public downloadFile(response: any, fileName?: string) {
    const blob = new Blob([response.body], { type: response.headers.get('content-type') });
    fileName = fileName || response.headers.get('content-disposition').split(';')[0];
    const file = new File([blob], fileName, { type: response.headers.get('content-type') });
    saveAs(file);
}

这还将解决@knbibin raised关于使用自定义文件名的问题。

答案 5 :(得分:0)

您需要在您的获取请求中添加 { responseType : 'application/octet-stream'} 作为无需调用 post 方法

{ responseType : 'application/octet-stream'}

在 .ts 文件中

DownLoadExcel(){
    this.MprService.downLoadRFQInfoExcel(this.revisionId).subscribe(data =>{this.downloadFile(data)});
}
    
downloadFile(data: Blob) { 
    const contentType = 'application/vnd.openxmlformats-ficedocument.spreadsheetml.sheet'; 
    const blob = new Blob([data], { type: contentType });
    const url = window.URL.createObjectURL(blob);
    window.open(url);
}