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

knb*_*bin 12 api excel post angular

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

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

组件.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);
}
Run Code Online (Sandbox Code Playgroud)

名称Service.ts

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

httpService.ts

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

使用上面的代码库,我遇到了两个错误并且文件没有下载。

  1. 得到错误:

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

  1. 如果我更改数据,(downloadFile(data: any))则会出现上述任何错误(1),但我收到的httperror响应为“语法错误:json 中位置 0 处的意外标记 Pjson.parse

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

Adr*_*rma 10

添加标题 { responseType: 'blob'}

像这样:

this.http.post<any>(apiEndpoint,request,{ responseType: 'blob'} )
Run Code Online (Sandbox Code Playgroud)


dee*_*lde 10

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

  2. 您需要在创建 blob 文件时传入正确的 MIME 类型。(fe application/octet-streamapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet)。

组件.ts

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

  • 如何获取特定文件名的文件?说“NameList.xlsx”? (5认同)

小智 6

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

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

响应 - 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(response);
    link.download = fileName;
    link.click();
  }
Run Code Online (Sandbox Code Playgroud)


小智 5

虽然{ responseType: 'blob'}像这里的大多数答案所说的那样使用有效,但我建议使用responseType: 'arraybuffer'而不是blobwith observe: 'response'。您的电话将如下所示:

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

这样做的好处有两个:

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

我用这个方法把文件名和的MIME类型arraybufferContent-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);
}
Run Code Online (Sandbox Code Playgroud)

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