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);});
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With