Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 6 Downloading file from rest api

I have my REST API where I put my pdf file, now I want my angular app to download it on click via my web browser but I got HttpErrorResponse

"Unexpected token % in JSON at position 0"

"SyntaxError: Unexpected token % in JSON at position 0↵ at JSON.parse (

this is my endpoint

    @GetMapping("/help/pdf2") public ResponseEntity<InputStreamResource> getPdf2(){      Resource resource = new ClassPathResource("/pdf-sample.pdf");     long r = 0;     InputStream is=null;      try {         is = resource.getInputStream();         r = resource.contentLength();     } catch (IOException e) {         e.printStackTrace();     }          return ResponseEntity.ok().contentLength(r)                 .contentType(MediaType.parseMediaType("application/pdf"))                 .body(new InputStreamResource(is));  } 

this is my service

  getPdf() {  this.authKey = localStorage.getItem('jwt_token');  const httpOptions = {   headers: new HttpHeaders({     'Content-Type':  'application/pdf',     'Authorization' : this.authKey,     responseType : 'blob',     Accept : 'application/pdf',     observe : 'response'   }) }; return this.http   .get("http://localhost:9989/api/download/help/pdf2", httpOptions); 

}

and invocation

this.downloadService.getPdf()   .subscribe((resultBlob: Blob) => {   var downloadURL = URL.createObjectURL(resultBlob);   window.open(downloadURL);}); 
like image 974
gmexo Avatar asked Sep 03 '18 18:09

gmexo


People also ask

How can I download file in angular?

Angular Download Link You'll use an anchor tag pointing to the file with the href attribute. The download attribute informs the browser that it shouldn't follow the link but rather download the URL target. You can also specify its value in order to set the name of the file being downloaded.


Video Answer


1 Answers

I solved the issue in this way (please note that I have merged multiple solutions found on stack overflow, but I cannot find the references. Feel free to add them in the comments).

In My service I have:

public getPDF(): Observable<Blob> {    //const options = { responseType: 'blob' }; there is no use of this     let uri = '/my/uri';     // this.http refers to HttpClient. Note here that you cannot use the generic get<Blob> as it does not compile: instead you "choose" the appropriate API in this way.     return this.http.get(uri, { responseType: 'blob' }); } 

In the component, I have (this is the part merged from multiple answers):

public showPDF(fileName: string): void {     this.myService.getPDF()         .subscribe(x => {             // It is necessary to create a new blob object with mime-type explicitly set             // otherwise only Chrome works like it should             var newBlob = new Blob([x], { type: "application/pdf" });                          // IE doesn't allow using a blob object directly as link href             // instead it is necessary to use msSaveOrOpenBlob             if (window.navigator && window.navigator.msSaveOrOpenBlob) {                 window.navigator.msSaveOrOpenBlob(newBlob, fileName);                 return;             }                          // For other browsers:              // Create a link pointing to the ObjectURL containing the blob.             const data = window.URL.createObjectURL(newBlob);                          var link = document.createElement('a');             link.href = data;             link.download = fileName;             // this is necessary as link.click() does not work on the latest firefox             link.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }));                          setTimeout(function () {                 // For Firefox it is necessary to delay revoking the ObjectURL                 window.URL.revokeObjectURL(data);                 link.remove();             }, 100);         }); } 

The code above works in IE, Edge, Chrome and Firefox. However, I don't really like it, as my component is pulluted with browser specific stuff which will surely change over time.

like image 54
Yennefer Avatar answered Sep 21 '22 19:09

Yennefer