2

I am trying to implement download file functionality in my angular 4 app. My api returns base 64 string of the file which I download from SharePoint. I am using file-saver module to get the file downloaded. Below is the code used.

let byteArray = new Uint8Array(res.data)
 , blob = new Blob([byteArray], {type: 'application/pdf'});
 saveAs(blob, "test.pdf");

res.data is the base64 string of file. The file gets downloaded, however, could not be opened. The error message is "file is corrupted or damaged". Text file gets downloaded and can be opened but is alway blank with no content. Am I doing something wrong.

Ravi Kukreja
  • 627
  • 1
  • 8
  • 17
  • Turns out I was converting base64 to blob in an incorrect way. This [link](https://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript) helped me. – Ravi Kukreja Mar 15 '18 at 17:38

4 Answers4

3

It's hard to know what is wrong without being able to test the actual request/response.

I would try to log the different objects and analyse the output, maybe cast the response directly to new Blob, and see what happens.

Another tips might be to test without using file-saver. Maybe something like this:

downloadFile(data: Response){
  var blob = new Blob([data], { type: 'application/pdf' });
  var url= window.URL.createObjectURL(blob);
  window.open(url);
}

Source: How do I download a file with Angular2

Naoe
  • 1,209
  • 8
  • 12
  • I am following your answer and I am not able to understand it's behaviour. Sometimes it downloads the file and mostly it does not. – Adnan Sheikh Aug 21 '19 at 06:23
2

For Angular 6 +

1 - Install dependencies for show save/open file pop-up

npm install file-saver --save
npm install @types/file-saver --save

2- Create a service with this function to recive the data

import { RequestOptions, ResponseContentType, Http } from '@angular/http';
import { map } from 'rxjs/operators';
    constructor(private http: Http) { }

    downloadFile(id): Observable<Blob> {
        let options = new RequestOptions({responseType: ResponseContentType.Blob });
        return this.http.get(this.baseUrl + `coursepurchased/receipt/` + bookingId, options)
        .pipe(map(res => res.blob()))
    }

3- In the component parse the blob with 'file-saver'

import {saveAs as importedSaveAs} from "file-saver";

 getCourseReceipt(bookingId) {
    this.studentInfoService.getCourseInvoice(bookingId).subscribe(
      blob => {
        var fileName = 'test.pdf';
        importedSaveAs(blob, fileName)
      },
      error => {
        console.log(error);
        this.alertService.showAlert(error.message, "error");
      }
    );
  }

This works for me!

Sachin from Pune
  • 656
  • 8
  • 19
  • i tryed it the same way and get the following build error: BUILD ERROR 'saveAs' is not exported by node_modules/file-saver/dist/FileSaver.min.js – Andre Aus B Jan 28 '20 at 19:55
1

Turns out I was converting base64 to blob in an incorrect way. This base64 to blob helped me.

Ravi Kukreja
  • 627
  • 1
  • 8
  • 17
0

Call the function in the component like so:

 getPdf(form) {
   this.formService.getFormPdf(form.id).subscribe(data => {
     saveAs(data, form.name + '_' + form.surname + '.pdf');
     this.toastr.toastrSuccess.next('PDF fetched');
   });
 }

then implement in http service like so:

  getFormPdf(formNumber): Observable<any> {
    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    headers.append('Authorization', 'Token ' + localStorage.getItem('token'));
    return this.http.get(this.PDFForm + formNumber, { headers: headers, responseType: ResponseContentType.Blob }).map(
        (res) => {
            return new Blob([res.blob()], { type: 'application/pdf' });
        });
}
Klemen Fajs
  • 148
  • 2
  • 6