localhost
localhost

Reputation: 861

Download file not working

I am new to Javascript, I want to download a file that comes from a dynamic url after the result of a promise, it is a generated pdf which I am trying to download with the following call but unable to make it work as download doesn't start.

<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
})
}

Here is plunk

Upvotes: 19

Views: 17672

Answers (10)

sebu
sebu

Reputation: 2954

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

downloadMyFile(){
  .then((result)=>{
       var a= document.createElement('a');
       a.href = result;
       a.download = 'download name';
       a.click();
   }).catch((error)=>{})
}

Upvotes: 1

Olemak
Olemak

Reputation: 2131

Javascript is not really required for this, so I will suggest the laziest and easiest possible solution - to simply use a basic html tag instead.

Instead of a button, use an anchor tag with the download keyword:

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

Very old browsers that does not support HTML5 will fail elegantly - instead of downloading the target, older browsers will simply display the target in the browser. That's very graceful degradation and a fully acceptable fallback.

You can style the anchor to look like whatever you want with css, and is also the most semantically correct tag: anchors are for links (and this is a link) while buttons are for interacting with forms (like submit) or other interactions with the UI. THe end user won't know or care what tag you use anyway.

If the url will be changed, like getting different parameters based on interactions with the UI, you could always use javascript to update the URL on the tag - but that is a different question.

Reference for Anchor tag on MDN

Upvotes: 0

Bangash
Bangash

Reputation: 127

you can download any dynamic file by just write a download in the tag where you have fetch the url to the file. try this and let me know if it work for you.

here is the working example:

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

Upvotes: 0

Dilip Nannaware
Dilip Nannaware

Reputation: 1480

Here is the code that works for downloadign the API respone in IE and chrome/safari. Here response variable is API response.

 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);
    }

Upvotes: 0

Karthik S
Karthik S

Reputation: 313

You can download the response of your promise like mentioned below:

 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
      })
  }

Upvotes: 0

St&#233;phane GRILLON
St&#233;phane GRILLON

Reputation: 11864

use saveAs() function with npm install @types/file-saver --save-dev

or in package.json:

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

Sample to export CSV file:

HTML:

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

Component:

import { FooService } from '../services/foo.service';

constructor(private fooService: FooService) { }

async exportCsv() {
  this.fooService.exportCsv(this.fooid);
}

Service (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);
    }
  }

Upvotes: 0

Martin Ad&#225;mek
Martin Ad&#225;mek

Reputation: 18389

You can force download file like this:

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

Simply create anchor tag, set its href and download attributes and trigger click event.

Also note that this is not really about URL ending with extension or not - it is more about the headers that you send with the file response (namely Content-Type and Content-Disposition).

Upvotes: 8

tatsu
tatsu

Reputation: 2536

(3 different files) in app.module.ts :

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

in 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;
}

and in 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');
  }

Upvotes: 0

Rahul Bisht
Rahul Bisht

Reputation: 144

instead of making ajax request to download file just do the following.

window.open(url);

Upvotes: 0

Saeed
Saeed

Reputation: 5488

Use this line of codes:

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

OR You can use pdf.js from 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);
    });;

Source and Complete code: http://usefulangle.com/post/20/pdfjs-tutorial-1-preview-pdf-during-upload-wih-next-prev-buttons

Upvotes: 0

Related Questions