简体   繁体   English

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

[英]How to download an excel file in Angular 8 as an API response

I've an API which returns an excel document as response.我有一个 API,它返回一个 excel 文档作为响应。 The request will be one simple json.请求将是一个简单的 json。

I've searched google and found some code base to download the file and I've used it in my application, but I'm getting some errors and unable to find it out the solution.我搜索了谷歌,找到了一些代码库来下载文件,我在我的应用程序中使用了它,但我遇到了一些错误,无法找到解决方案。 Below are my code base.下面是我的代码库。

component.ts组件.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名称服务.ts

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

httpService.ts http服务.ts

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

with the above code base I'm getting below two errors and the file is not downloaded.使用上面的代码库我得到以下两个错误并且文件未下载。

  1. Getting the error:得到错误:

"Type Response is not assignable to type Blobpart" in creating the Blob(const blob = new Blob([data], { type: '.xlsx' });)在创建 Blob(const blob = new Blob([data], { type: '.xlsx' }); 时“类型响应不可分配给类型 Blobpart”

  1. If I change the data as any (downloadFile(data: any)) the above error(1) will go but I'm getting an httperror response as 'Syntax error: unexpected token P in json at position 0 at json.parse如果我将数据更改为任何(downloadFile(data: any))以上错误 (1) 将 go 但我收到一个httperror响应 '语法错误:json 中的意外令牌 P position 0 json.parse

Kindly help if anyone finds any solution to the above issues.如果有人找到上述问题的任何解决方案,请提供帮助。

Add header { responseType: 'blob'}添加 header { responseType: 'blob'}

Like this:像这样:

this.http.post<any>(apiEndpoint,request,{ responseType: 'blob'} )
  1. You need to set the response-header { responseType: 'blob'} in the request.您需要在请求中设置 response-header { responseType: 'blob'}

  2. You need to pass in the correct MIME-Type as you'are creating the blob-file.您需要在创建 blob 文件时传入正确的 MIME-Type。 (fe application/octet-stream or application/vnd.openxmlformats-officedocument.spreadsheetml.sheet ). (fe application/octet-streamapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet )。

component.ts组件.ts

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

While using { responseType: 'blob'} as said by most answers here works, I'd suggest using responseType: 'arraybuffer' instead of blob with observe: 'response' .虽然使用{ responseType: 'blob'}正如这里大多数答案所说的那样有效,但我建议使用responseType: 'arraybuffer'而不是blobobserve: 'response' Your call would then look like this:您的电话将如下所示:

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

The advantage of this is two-fold:这样做的好处有两个:

  1. Arraybuffer is a generic stream of bytes and the Blob object can be created using either a blob or an arraybuffer , using the Content-Type Arraybuffer 是一个通用的 stream 字节和 Blob object 可以使用blobarraybuffer ,使用Content-Type
  2. observe: 'response' will also include the response headers that you set at the server in the parsed response. observe: 'response'还将包括您在解析的响应中在服务器上设置的响应标头。

I use this method to put the filename and the MIME Type of the arraybuffer in the Content-Disposition and Content-Type response headers and then use a generic download service at the client-side.我使用此方法将arraybuffer的文件名和 MIME 类型放入Content-DispositionContent-Type响应标头中,然后在客户端使用通用下载服务。

Also, I would suggest using a File object instead of just the Blob , which gives you the flexibility of giving it a filename like so:另外,我建议使用File object 而不仅仅是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);
}

This will also solve the problem that @knbibin raised about using a custom filename.这也将解决@knbibin 提出的关于使用自定义文件名的问题。

Set response-header { responseType: 'blob'} in the request.在请求中设置 response-header { responseType: 'blob'}

To download the excel, use the below function.要下载 excel,请使用下面的 function。

response - api response, fileName- excel name响应 - 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();
  }

To download the file use the below code要下载文件,请使用以下代码

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

You need to Add { responseType: 'application/octet-stream'} in your get request as No need to call post method您需要在 get 请求中添加 { responseType: 'application/octet-stream'} ,因为不需要调用 post 方法

{ responseType : 'application/octet-stream'}

And in.ts file和 in.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);
}

If anyone wants only to download a file from assets, they can use this code:如果有人只想从资产中下载文件,他们可以使用以下代码:

<a href="./assets/files/file.xlsx" target="_blank"></a>

But you need to mention the location in angular.json但是你需要在angular.json中提及位置

"architect": {
   "build": {
      "options": {
    "assets": [
                  "src/assets/files"
              ]
      }
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM