I use a-element as download-button for files I have had to query with AJAX before as described here, here and here. I put to put the file-data as Data-URI into a a-element to create a download-button. Unfortunately I can not just point to the file but have to do it like that. With most download-formats HTML, CSV it works like this:
var mimeType = "text/html"; // example. works also with others.
var BOM = '\ufeff';
var url = "data:"+ mimeType +";charset=UTF-8," + BOM + encodeURIComponent(response.data);
var linkElem = document.querySelector("#hiddenDownloadLink");
var link = angular.element(linkElem);
link.prop("href", url);
link.prop("download", 'myFile.' + extension);
linkElem.click();
Okay. That works. But not for PDF.
I create a PDF in my backend (java, with openhtmltopdf but it doesn't matter I guess, since the PDF is definitely correct):
httpOutputMessage.getHeaders().add(HttpHeaders.CONTENT_TYPE, "application/pdf");
httpOutputMessage.getHeaders().add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"myFile.pdf\"");
makePdf(httpOutputMessage.getBody());
If I query the backend directly, or even if I log the output into a file, everything is fine. But when I use my download-controller as described above, I get a PDF with the right number of pages but completely empty! I think there must be an encoding issue. I tried with and without BOM, also with or without encodeURIComponent.
I also tried to use the base64-decoding as. Because window.atob(response.data) fails because of line breaks and others, I tried this conversion. The result is an broken PDF. Results in broken PDFs. I am not sure if that makes any sense.
My PDF-data starts like this, so it's not compressed or encoded anyhow:
%PDF-1.4
%����
1 0 obj
<<
/Type /Catalog
/Version /1.7
/Pages 2 0 R
>>
endobj
3 0 obj
<<
I also tried to convert the bytestream to blob and generate a link as described here orhere, but that creates broken PDFs.
Any Ideas, why I get empty PDFs or what might go wrong here and how can I repait the download-link?
-- Edit 1
I also get valid, but blank PDF when I try
var blob = new Blob([response.data], {type: 'application/pdf'});
var url = window.URL.createObjectURL(blob);
link.prop("href", url);
When I pipe response.data through this function, I get a broken PDF.
var utf8_to_b64 = function(str) {
var unescape = window.unescape || window.decodeURI;
str = encodeURIComponent(str);
str = unescape(str);
str = window.btoa(str);
return str;
};
So I could fully reproduce your situation. I loaded and output a 4 page PDF file through an AJAX request from backend, and with your code example got a 4 page blank PDF.
Here's what I did after (and got the right PDF to download):
I base64 encoded the output from the backend. In my case I was using PHP so it was something like this:
$pdf = file_get_contents('test.pdf');
header('Content-Type: application/pdf');
echo base64_encode($pdf);
Then in the frontend I changed only this line:
var url = "data:"+ mimeType +";charset=UTF-8," + BOM + encodeURIComponent(response.data);
to this:
var url = "data:"+ mimeType +";base64," + encodeURIComponent(response.data);
Hope this helps.