El Hombre Sin Nombre
El Hombre Sin Nombre

Reputation: 3102

Angular 2 - Download File form Rest API (CSV)

I´m trying to download a file from a API . When I onclick button launch this function.

download(form:any){
        this.fileCtrl.download().subscribe(
          (response:any) => {
            const blob = new Blob([response], { type: 'text/csv' });
            console.log(blob);
            const url= window.URL.createObjectURL(blob);
            window.open(url);  
          },
          error => {
            console.log(error);
          }
        )}
    }

The function return this error. Load the image because is "complex" error.

Error

UPDATE

  download() {
    return this.http.get(
      "URL",
      {
        headers: new HttpHeaders({
          Authorization: "Token " + localStorage.getItem("token")
        })
      }
    );
  }

Upvotes: 1

Views: 5274

Answers (2)

Chaitanya
Chaitanya

Reputation: 939

Instead of using third party library you can do following.

  1. Get Content-type from the response headers
  2. Get Content-disposition headers
  3. Get the Content-Diposition attachment
  4. Set the file name
  5. Create <a> tag and set downlaod attribute
  6. Create click event on the <a>
  7. Dispatch the click event.

    this.http.get(apiURL).subscribe(res =>{

    // support Chrome

      const isChrome =
        /Chrome/.test(navigator.userAgent) &&
        /Google Inc/.test(navigator.vendor);
    
      // support firefox
      const isFirefox =
        navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
    
      // support IE
      const isIe =
        !!navigator.userAgent.match(/Trident/g) ||
        !!navigator.userAgent.match(/MSIE/g);
    
      // get the content-type from the response headers
      let contentType = null;
      contentType = res.headers.get('Content-Type');
    
      // get content-disposition headers
      const contentDispositionHeader = res.headers.get('Content-Disposition');
    
      // get the Content-Diposition attachment; filename='x.csv'
      const result = contentDispositionHeader
        .split(';')[1]
        .trim()
        .split('=')[1];
    
      // get the file name
      const fileName = result.replace(/'/g, '');
    
      // check if the response and attachment exists, and create anchor tag
    
      if (res && /attachment/.test(contentDispositionHeader)) {
        // for chrome and firefox
        if (isChrome || isFirefox) {
          const linkElement = document.createElement('a');
          const blob = new Blob([res['_body']], { type: contentType });
          const url = window.URL.createObjectURL(blob);
          linkElement.setAttribute('href', url);
          linkElement.setAttribute('download', fileName);
    
          // create a click event on the anchor tag
          const clickEvent = new MouseEvent('click', {
            view: window,
            bubbles: true,
            cancelable: false
          });
    
          // dispatch the click event
          linkElement.dispatchEvent(clickEvent);
        } else {
          // for IE
          if (isIe) {
            let blob3;
            blob3 = new Blob([res['_body']]);
            if (window.navigator.msSaveOrOpenBlob) {
              window.navigator.msSaveBlob(blob3, fileName);
            }
          }
        }
      }
    })
    

Upvotes: 0

Adrita Sharma
Adrita Sharma

Reputation: 22203

The Http call should have header { responseType: 'blob' }:

Try like this:

this.http.get(url, { responseType: 'blob' })

Once you get the byteArray, use File-Saver to download the file.

import saveAs from 'file-saver';

 this.fileCtrl.download().subscribe(
      (response:any) => {
         saveAs(resp, `file.csv`)
 });

Upvotes: 4

Related Questions