【问题标题】:Set File Name while downloading via blob in Angular 5在Angular 5中通过blob下载时设置文件名
【发布时间】:2019-01-28 07:41:25
【问题描述】:

下面是我从 API 下载文件的 Typescript 代码

DownloadLM() {
var ID= sessionStorage.getItem("UserID");
    return this.http.get(this.baseurl + 'api/DownloadFiles/DownloadLM/' + ID,
      {
        headers: {
          'Content-Type': 'application/json'
        },
        responseType: 'arraybuffer'
      }
    )
      .subscribe(respData => {
        this.downLoad(respData, this.type);
      }, error => {
      });
  }

  downLoad(data: any, type: string) {
    var blob = new Blob([data], { type: type.toString() });
    var url = window.URL.createObjectURL(blob);
    var pwa = window.open(url);
    if (!pwa || pwa.closed || typeof pwa.closed == 'undefined') {
      alert('Please disable your Pop-up blocker and try again.');
    }
  }

这很好下载Excel文件,但它给我不想要的文件一个随机名称,我想在下载时设置我选择的文件名,

在哪里可以设置文件名? Blob 的任何属性?

【问题讨论】:

    标签: angular azure angular5 blob


    【解决方案1】:

    你可以将下载属性设置为你想要的文件名,将href设置为对象url,然后只需调用click

    var blob = new Blob([data], { type: type.toString() });
    var url = window.URL.createObjectURL(blob);
    var anchor = document.createElement("a");
    anchor.download = "myfile.txt";
    anchor.href = url;
    anchor.click();
    

    【讨论】:

    • 谢谢,它可以工作,但我也在检查弹出窗口是否在浏览器中被阻止,为此我写了 var pwa = anchor.click(); if (!pwa || pwa.closed || typeof pwa.closed == 'undefined') { alert('请禁用您的弹出窗口拦截器并重试。'); } ,但在您的代码中无法检查它,因为 anchor.click() 不返回窗口
    • 你可能需要在那里做一个黑客,如果这有帮助,请投票
    • 因为它发生在基于 JS 的框架中,并且 JS 可以被禁用,所以也需要注意这一点(弹出启用消息),它部分帮助没有完全
    • 当它抛出“HtmlAnchorElement 类型上不存在属性'下载'”将其设置为 anchor.setAttribute("download", "");作品
    【解决方案2】:

    如果您想要上传文件的确切文件名,请从支持的 API 流中设置文件名的自定义标头。

    您可以这样使用它:我的 Excel API 响应标头:

    content-disposition: inline;filename="salesReport.xls" 
    content-type: application/octet-stream 
    date: Wed, 22 Aug 2018 06:47:28 GMT 
    expires: 0 
    file-name: salesReport.xls 
    pragma: no-cache 
    transfer-encoding: chunked 
    x-application-context: application:8080 
    x-content-type-options: nosniff 
    x-xss-protection: 1; mode=block
    

    Service.ts

    excel(data: any) {
      return this.httpClient.post(this.config.domain + 
      `/api/registration/excel/download`,data, {observe: 'response', responseType: 'blob'})
      .map((res) => {
          let data = {
                         image: new Blob([res.body], {type: res.headers.get('Content-Type')}),
                         filename: res.headers.get('File-Name')
                      }
        return data ;
      }).catch((err) => {
        return Observable.throw(err);
      });
    }
    

    Component.ts

    excelDownload (data) {
       this.registration.excel(data).subscribe(
        (res) => {
         const element = document.createElement('a');
          element.href = URL.createObjectURL(res.image);
          element.download = res.filename;
          document.body.appendChild(element);
          element.click();
         this.toastr.success("Excel generated  successfully");
        },
      (error) =>{
         this.toastr.error('Data Not Found');
      });
    }
    

    【讨论】:

    • res.headers.get('File-Name') 有帮助。 tnx.
    【解决方案3】:

    由于有些人要求提供带有承诺的版本,因此您可以使用 await 和 async:

    第 1 部分:从服务器获取 Blob:

      generateSapExcel(data: GenerateSapExport): Promise<HttpResponse<Blob>> {
        return this.http.post(`${this.pathprefix}/GenerateSapExcel`, data, { responseType: 'blob', observe: 'response' })
          .toPromise()
          .catch((error) => this.handleError(error));
      }
    

    第 2 部分:提取 HttpResponse 并将其传递给用户:

    public downloadFile(data: HttpResponse<Blob>) {
        const contentDisposition = data.headers.get('content-disposition');
        const filename = this.getFilenameFromContentDisposition(contentDisposition);
        const blob = data.body;
        const url = window.URL.createObjectURL(blob);
        const anchor = document.createElement("a");
        anchor.download = filename;
        anchor.href = url;
        anchor.click();
      }
    
      private getFilenameFromContentDisposition(contentDisposition: string): string {
        const regex = /filename=(?<filename>[^,;]+);/g;
        const match = regex.exec(contentDisposition);
        const filename = match.groups.filename;
        return filename;
      }
    

    第 3 部分:结合两者:

          const blobresponse = await this.dataService.generateSapExcel(dataToSend);
          this.downloadService.downloadFile(blobresponse);
    

    第 4 部分:服务器:

            [HttpPost]
            [Route(nameof(GenerateSapExcel))]
            public async Task<FileStreamResult> GenerateSapExcel(GenerateSapExportDto dto)
            {
                Stream stream = await _sapKurepoService.GenerateSapExcel(dto);
                FileStreamResult result = File(stream, FileHelper.ContentypeExcel, "excel.xlsx");
                return result;
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-15
      • 2017-01-08
      • 2018-05-04
      • 1970-01-01
      • 1970-01-01
      • 2019-05-01
      • 1970-01-01
      • 2019-11-05
      相关资源
      最近更新 更多