【问题标题】:How to download an excel file in Angular 8 as an API response如何在 Angular 8 中下载 excel 文件作为 API 响应
【发布时间】:2020-02-08 15:50:24
【问题描述】:

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

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

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. 得到错误:

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

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

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

【问题讨论】:

    标签: excel angular api post


    【解决方案1】:

    添加标题{ responseType: 'blob'}

    像这样:

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

    【讨论】:

    • 我已将 HttpHeader 设置为 blob 但仍然是同样的问题。
    【解决方案2】:
    1. 需要在请求中设置response-header{ responseType: 'blob'}

    2. 您需要在创建 blob 文件时传入正确的 MIME-Type。 (例如 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);
    }
    

    【讨论】:

    • 如何获取指定文件名的文件?说“NameList.xlsx”?
    【解决方案3】:

    使用以下代码下载文件

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

    【讨论】:

    • 根据免费词典“fs”有 195 个定义。在此处查看:acronyms.thefreedictionary.com/FS 因此,为了清楚起见,请做出微小但重要的努力,以阐明 fs.saveAs(...) 的含义。只是粘贴代码并不酷。这实际上是一个 npm 包 (npmjs.com/package/file-saver),它允许您从浏览器将流保存到文件系统,这回答了上面发布的问题。
    【解决方案4】:

    虽然使用{ 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 创建 Blob 对象,使用 Content-Type
    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】:

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

    要下载excel,请使用以下函数。

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

    【讨论】:

      【解决方案6】:

      您需要在 get 请求中添加 { 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);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-19
        相关资源
        最近更新 更多