如何从HttpClient下载文件

Jea*_*los 16 blob file typescript angular angular-httpclient

我需要从我的后端下载一个excel,它返回一个文件.

当我提出请求时,我收到错误:

TypeError:您提供了"undefined",其中包含了一个流.您可以提供Observable,Promise,Array或Iterable.

我的代码是:

this.http.get(`${environment.apiUrl}/...`)
      .subscribe(response => this.downloadFile(response, "application/ms-excel"));
Run Code Online (Sandbox Code Playgroud)

我试过get和map(...)但是没有用.

细节:角度5.2

引用:

import { HttpClient } from '@angular/common/http';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/finally';
import 'rxjs/add/operator/map'
import 'rxjs/add/operator/catch';
Run Code Online (Sandbox Code Playgroud)

内容 - 响应类型:

Content-Type: application/ms-excel
Run Code Online (Sandbox Code Playgroud)

怎么了?

Unl*_*yAj 29

尝试这样的事情:

类型:application/ms-excel

/**
 *  used to get file from server
 */

this.http.get(`${environment.apiUrl}`,{
          responseType: 'arraybuffer',headers:headers} 
         ).subscribe(response => this.downLoadFile(response, "application/ms-excel"));


    /**
     * Method is use to download file.
     * @param data - Array Buffer data
     * @param type - type of the document.
     */
    downLoadFile(data: any, type: string) {
        let blob = new Blob([data], { type: type});
        let url = window.URL.createObjectURL(blob);
        let pwa = window.open(url);
        if (!pwa || pwa.closed || typeof pwa.closed == 'undefined') {
            alert( 'Please disable your Pop-up blocker and try again.');
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 我使用 Angular 9 时遇到错误:类型“arraybuffer”不可分配给类型“json”。ts(2322) http.d.ts(1097, 9):预期类型来自属性“responseType”。 (4认同)

Has*_*san 23

从后端返回带有文件类型的Blob.以下函数将接受任何文件类型和弹出下载窗口:

downloadFile(route: string, filename: string = null): void{

    const baseUrl = 'http://myserver/index.php/api';
    const token = 'my JWT';
    const headers = new HttpHeaders().set('authorization','Bearer '+token);
    this.http.get(baseUrl + route,{headers, responseType: 'blob' as 'json'}).subscribe(
        (response: any) =>{
            let dataType = response.type;
            let binaryData = [];
            binaryData.push(response);
            let downloadLink = document.createElement('a');
            downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, {type: dataType}));
            if (filename)
                downloadLink.setAttribute('download', filename);
            document.body.appendChild(downloadLink);
            downloadLink.click();
        }
    )
}
Run Code Online (Sandbox Code Playgroud)

  • 好答案!我还要添加“ downloadLink.parentNode.removeChild(downloadLink);” 在“ downloadLink.click();”之后。只是为了保持清楚。 (2认同)
  • 为什么‘blob’为‘json’`?我想你只能说“responseType: 'blob'”。 (2认同)

Use*_*716 19

我花了一段时间来实现其他响应,因为我使用的是 Angular 8 (tested up to 10)。我最终得到了以下代码(深受哈桑启发)。

请注意,要设置名称,标头Access-Control-Expose-Headers必须包含Content-Disposition. 要在 Django RF 中进行设置:

http_response = HttpResponse(package, content_type='application/javascript')
http_response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
http_response['Access-Control-Expose-Headers'] = "Content-Disposition"
Run Code Online (Sandbox Code Playgroud)

在角度:

  // component.ts
  // getFileName not necessary, you can just set this as a string if you wish
  getFileName(response: HttpResponse<Blob>) {
    let filename: string;
    try {
      const contentDisposition: string = response.headers.get('content-disposition');
      const r = /(?:filename=")(.+)(?:;")/
      filename = r.exec(contentDisposition)[1];
    }
    catch (e) {
      filename = 'myfile.txt'
    }
    return filename
  }

  
  downloadFile() {
    this._fileService.downloadFile(this.file.uuid)
      .subscribe(
        (response: HttpResponse<Blob>) => {
          let filename: string = this.getFileName(response)
          let binaryData = [];
          binaryData.push(response.body);
          let downloadLink = document.createElement('a');
          downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, { type: 'blob' }));
          downloadLink.setAttribute('download', filename);
          document.body.appendChild(downloadLink);
          downloadLink.click();
        }
      )
  }

  // service.ts
  downloadFile(uuid: string) {
    return this._http.get<Blob>(`${environment.apiUrl}/api/v1/file/${uuid}/package/`, { observe: 'response', responseType: 'blob' as 'json' })
  }

Run Code Online (Sandbox Code Playgroud)

  • 谢谢,除了正则表达式之外它都有效,我使用的是 asp.net,所以内容配置有点不同,我的看起来像这样: '/(?:filename=)(.+)(?:;)/' (2认同)

Sha*_*r M 9

使用 API 中的 Blob 输出(Excel 文件)

并调整了@gabrielrincon 答案

downloadExcel(): void {
const payload = {
  order: 'test',
  };

this.service.downloadExcel(payload)
  .subscribe((res: any) => {
    this.blobToFile(res, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "Export.xlsx");
  });}
Run Code Online (Sandbox Code Playgroud)

blob 转文件常用函数

blobToFile(data: any, type: string, fileName: string) {
 const a = document.createElement('a');
 document.body.appendChild(a);
 a.style.display = 'none';
 const blob = new Blob([data], { type: type });
 const url = window.URL.createObjectURL(blob);
 a.href = url; a.download = fileName; a.click();
 window.URL.revokeObjectURL(url);}
Run Code Online (Sandbox Code Playgroud)

在 blob 到文件函数中,我们期望第一个参数作为 blob 数据、文件类型并传递文件名(包括扩展名) 1. 我们正在创建一个 html a 标签元素 2. 然后我们将该元素附加到 html 中 3. 然后隐藏 a标签元素 4. 然后使用文件和类型创建新的 blob 对象 5. 我们将 blob 对象转换为 URL 6. 然后将该 URL 附加到我们的 a 标签的 href 属性 7. 我们在窗口中打开 URL,以便它将下载


Mik*_*ael 5

当我使用 post\xe2\x80\x9d 搜索 \xe2\x80\x9drxjs 下载文件时,我最终来到这里。

\n\n

这是我的最终产品。它使用服务器响应中给出的文件名和类型。

\n\n
import { ajax, AjaxResponse } from \'rxjs/ajax\';\nimport { map } from \'rxjs/operators\';\n\ndownloadPost(url: string, data: any) {\n    return ajax({\n        url: url,\n        method: \'POST\',\n        responseType: \'blob\',\n        body: data,\n        headers: {\n            \'Content-Type\': \'application/json\',\n            \'Accept\': \'text/plain, */*\',\n            \'Cache-Control\': \'no-cache\',\n        }\n    }).pipe(\n        map(handleDownloadSuccess),\n    );\n}\n\n\nhandleDownloadSuccess(response: AjaxResponse) {\n    const downloadLink = document.createElement(\'a\');\n    downloadLink.href = window.URL.createObjectURL(response.response);\n\n    const disposition = response.xhr.getResponseHeader(\'Content-Disposition\');\n    if (disposition) {\n        const filenameRegex = /filename[^;=\\n]*=(([\'"]).*?\\2|[^;\\n]*)/;\n        const matches = filenameRegex.exec(disposition);\n        if (matches != null && matches[1]) {\n            const filename = matches[1].replace(/[\'"]/g, \'\');\n            downloadLink.setAttribute(\'download\', filename);\n        }\n    }\n\n    document.body.appendChild(downloadLink);\n    downloadLink.click();\n    document.body.removeChild(downloadLink);\n}\n
Run Code Online (Sandbox Code Playgroud)\n