【问题标题】:Download file not working下载文件不工作
【发布时间】:2018-04-20 14:31:33
【问题描述】:

我是 Javascript 新手,我想在承诺结果后下载来自动态 url 的文件,它是一个生成的 pdf,我试图通过以下调用下载但无法使其工作下载未开始。

<button (click)='downloadMyFile()'>Download</button>

downloadMyFile(){
  //url 
  .then((result)=>{
   //result is contains a url www.abc.com/file234
    window.location.href = result
})
  .catch((error)=>{
   //myerror
})
}

这里是plunk

【问题讨论】:

  • result的内容是什么?
  • @meskobalazs 在邮递员中我收到一个对话框说要下载文件。这是一个可下载的文件。
  • 在浏览器中打开结果 url 时会发生什么?或者,您可以将按钮包装在 &lt;a&gt; 中,然后在检索到的那个按钮上设置 href,以便以较少的 javascript-y 方式打开它。
  • 没有在按钮周围使用标签无效? url 传递了一些动态数据,这些数据使用该值来获取文件。
  • 你的代码没有意义。

标签: javascript angular


【解决方案1】:

您可以像这样强制下载文件:

const link = document.createElement('a');
link.href = result;
link.download = 'download';
link.target = '_blank';
link.click();

只需创建锚标记,设置其hrefdownload 属性并触发click 事件。

还请注意,这实际上与是否以扩展名结尾的 URL 无关 - 它更多的是与您随文件响应一起发送的标头(即 Content-TypeContent-Disposition)。

【讨论】:

    【解决方案2】:

    使用这行代码:

        //redirect current page to success page
        window.location="www.example.com/success.html";
        window.focus();
    

    或者你可以使用pdf.js 来自http://mozilla.github.io/pdf.js/

        PDFJS.getDocument({ url: pdf_url }).then(function(pdf_doc) {
            __PDF_DOC = pdf_doc;
            __TOTAL_PAGES = __PDF_DOC.numPages;
    
            // Hide the pdf loader and show pdf container in HTML
            $("#pdf-loader").hide();
            $("#pdf-contents").show();
            $("#pdf-total-pages").text(__TOTAL_PAGES);
    
            // Show the first page
            showPage(1);
        }).catch(function(error) {
    
            alert(error.message);
        });;
    

    源码及完整代码:http://usefulangle.com/post/20/pdfjs-tutorial-1-preview-pdf-during-upload-wih-next-prev-buttons

    【讨论】:

      【解决方案3】:

      只需执行以下操作,而不是发出 ajax 请求来下载文件。

      window.open(url);
      

      【讨论】:

        【解决方案4】:

        (3 个不同的文件)在app.module.ts 中:

         import {HttpClientModule} from '@angular/common/http';
         ...
         providers: [
            HttpClientModule,
            ...
        

        api.service.ts

        import {HttpClient, HttpErrorResponse, HttpHeaders, HttpParams, HttpResponse} from '@angular/common/http';
        ...
        public getMeMyPDF(): any {
            const url =  '/my/api/for/pdf';
            this.PDF = this.http.get(url, {
              observe: 'response',
              headers: new HttpHeaders({'Content-Type', 'application/pdf'}),
              responseType: 'text' as 'text' // <-- this part is rediculous but necessary
            }).catch(this.handleError);
            return this.PDF;
        }
        
        handleError(error: HttpErrorResponse) {
          console.log('an http get error happened.');
          console.error(error);
          let errorMessage;
          if (error.error instanceof Error) {
            errorMessage = `An error occurred: ${error.error.message}`;
          } else {
            errorMessage = `Server returned code: ${error.status}, error message is: ${error.message}`;
          }
          console.error(errorMessage);
          return errorMessage;
        }
        

        my.component.that.calls.api

        getMeAPDF(){
            this.apiService.getMeMyPDF().subscribe(res => {
              if(res !== null && res !== undefined){
                this.saveToFileSystem(res.body);
              }
            }, (error) => console.log(error), () => {});
          }
        
          private saveToFileSystem(response) {
            const blob = new Blob([response], { type: 'text/pdf' });
            const d = new Date();
            saveAs(blob, 'WOWPDF_' + this._datepipe.transform(d, 'yyyyMMdd_HHmmss') + '.pdf');
          }
        

        【讨论】:

          【解决方案5】:

          saveAs() 函数与npm install @types/file-saver --save-dev 一起使用

          或在 package.json 中:

            "dependencies": {
              "file-saver": "^1.3.3"
            }
          

          导出 CSV 文件的示例:

          HTML:

          <button (click)="exportCsv()" id="exportCsv" class="btn btn-primary" type="submit">CSV Export</button>
          

          组件:

          import { FooService } from '../services/foo.service';
          
          constructor(private fooService: FooService) { }
          
          async exportCsv() {
            this.fooService.exportCsv(this.fooid);
          }
          

          服务(fooService):

          import { saveAs } from 'file-saver';
          import { HttpParams, HttpResponse} from '@angular/common/http';
          
          exportCsv(fooid: string) {
              let params: HttpParams = new HttpParams();
              params = params.append('fooid', fooid);
              this.apiService.getCSVFile('api/foo/export', params).subscribe(response => this.saveToFileSystem(response)
              , error =>  this.errorProcessor(error));
          }
          
          private saveToFileSystem(response: HttpResponse<Blob>) {
              const contentDispositionHeader = response.headers.get('Content-Disposition');
              let filename = 'export.csv';
              if (contentDispositionHeader !== null) {
                const parts: string[] = contentDispositionHeader.split(';');
                filename = parts[1].split('=')[1];
              }
              const blob = response.body;
              if (blob !== null) {
                  saveAs(blob, filename);
              }
            }
          

          【讨论】:

            【解决方案6】:

            您可以下载您的承诺响应,如下所述:

             var triggerDownload = function(url, fileName) {
                  var a = document.createElement("a");
                  a.setAttribute("href", url);
                  a.setAttribute("download", fileName);
                  opts.container.append(a);
                  a.click();
                  $(a).remove();
              };
            
              downloadMyFile() {
                  promise
                   .then((result) => {
                      triggerDownload(result, 'xyz.pdf'); 
                    })
                   .catch((error) => {
                      //myerror
                  })
              }
            

            【讨论】:

              【解决方案7】:

              这是用于在 IE 和 chrome/safari 中下载 API 响应的代码。这里的响应变量是 API 响应。

               let blob = new Blob([response], {type: 'application/pdf'});
                  let fileUrl = window.URL.createObjectURL(blob);
                  if (window.navigator.msSaveOrOpenBlob) {
                      window.navigator.msSaveOrOpenBlob(blob, fileUrl.split(':')[1] + '.pdf');
                  } else {
                      window.open(fileUrl);
                  }
              

              【讨论】:

                【解决方案8】:

                您可以下载任何动态文件,只需在您已获取文件 url 的标签中写入下载。试试这个,让我知道它是否适合你。

                这里是工作示例:

                <a href="http://unec.edu.az/application/uploads/2014/12/pdf-sample.pdf" download>
                

                【讨论】:

                  【解决方案9】:

                  实际上并不需要Javascript,所以我会建议最懒惰和最简单的解决方案——简单地使用一个基本的html标签。

                  使用带有下载关键字的锚标记代替按钮:

                  <a href="www.abc.com/file234" download="SuggestedFileName">Download</a>
                  

                  不支持 HTML5 的非常旧的浏览器会优雅地失败 - 旧浏览器不会下载目标,而是简单地在浏览器中显示目标。这是非常优雅的降级和完全可以接受的回退。

                  您可以使用 css 设置锚点的样式,使其看起来像您想要的任何样式,这也是语义上最正确的标签:锚点用于链接(这是一个链接),而按钮用于与表单交互(如提交)或其他与 UI 的交互。最终用户无论如何都不会知道或关心您使用什么标签。

                  如果 URL 将被更改,例如根据与 UI 的交互获取不同的参数,您始终可以使用 javascript 来更新标签上的 URL - 但这是一个不同的问题。

                  Reference for Anchor tag on MDN

                  【讨论】:

                    【解决方案10】:
                    <button (click)='downloadMyFile()'>Download</button>
                    
                    downloadMyFile(){
                      .then((result)=>{
                           var a= document.createElement('a');
                           a.href = result;
                           a.download = 'download name';
                           a.click();
                       }).catch((error)=>{})
                    }
                    

                    【讨论】:

                    • 技术叫什么?语法对我来说似乎很陌生。
                    • 我会尝试,如果我的 ApiService 需要很长时间才能回复,我如何使用一些不以文件扩展名结尾的 url 模拟数据?
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-02-09
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多