PDF Download in HREF of a-element results in empty PDF
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;
};
javascript pdf data-uri
add a comment |
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;
};
javascript pdf data-uri
"since the PDF is definitely correct" - and how do you know this?
– Ryan McDonough
Nov 19 '18 at 10:30
As I wrote - I tested to call the backend directly with postman, and I wrote a pdf-file from backend on the servers harddrive, and in both cases it got a correct pdf with contents.
– Paflow
Nov 19 '18 at 13:29
add a comment |
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;
};
javascript pdf data-uri
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;
};
javascript pdf data-uri
javascript pdf data-uri
edited Nov 16 '18 at 10:17
Paflow
asked Nov 15 '18 at 14:59
PaflowPaflow
419622
419622
"since the PDF is definitely correct" - and how do you know this?
– Ryan McDonough
Nov 19 '18 at 10:30
As I wrote - I tested to call the backend directly with postman, and I wrote a pdf-file from backend on the servers harddrive, and in both cases it got a correct pdf with contents.
– Paflow
Nov 19 '18 at 13:29
add a comment |
"since the PDF is definitely correct" - and how do you know this?
– Ryan McDonough
Nov 19 '18 at 10:30
As I wrote - I tested to call the backend directly with postman, and I wrote a pdf-file from backend on the servers harddrive, and in both cases it got a correct pdf with contents.
– Paflow
Nov 19 '18 at 13:29
"since the PDF is definitely correct" - and how do you know this?
– Ryan McDonough
Nov 19 '18 at 10:30
"since the PDF is definitely correct" - and how do you know this?
– Ryan McDonough
Nov 19 '18 at 10:30
As I wrote - I tested to call the backend directly with postman, and I wrote a pdf-file from backend on the servers harddrive, and in both cases it got a correct pdf with contents.
– Paflow
Nov 19 '18 at 13:29
As I wrote - I tested to call the backend directly with postman, and I wrote a pdf-file from backend on the servers harddrive, and in both cases it got a correct pdf with contents.
– Paflow
Nov 19 '18 at 13:29
add a comment |
1 Answer
1
active
oldest
votes
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.
It helped because I realized that I had to do the BASE64 by myself. Then I used your url and it worked. Except that now you can not access backend directly, but that's not necessary.
– Paflow
Nov 29 '18 at 18:09
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53322226%2fpdf-download-in-href-of-a-element-results-in-empty-pdf%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
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.
It helped because I realized that I had to do the BASE64 by myself. Then I used your url and it worked. Except that now you can not access backend directly, but that's not necessary.
– Paflow
Nov 29 '18 at 18:09
add a comment |
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.
It helped because I realized that I had to do the BASE64 by myself. Then I used your url and it worked. Except that now you can not access backend directly, but that's not necessary.
– Paflow
Nov 29 '18 at 18:09
add a comment |
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.
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.
answered Nov 25 '18 at 21:36
Dan D.Dan D.
580313
580313
It helped because I realized that I had to do the BASE64 by myself. Then I used your url and it worked. Except that now you can not access backend directly, but that's not necessary.
– Paflow
Nov 29 '18 at 18:09
add a comment |
It helped because I realized that I had to do the BASE64 by myself. Then I used your url and it worked. Except that now you can not access backend directly, but that's not necessary.
– Paflow
Nov 29 '18 at 18:09
It helped because I realized that I had to do the BASE64 by myself. Then I used your url and it worked. Except that now you can not access backend directly, but that's not necessary.
– Paflow
Nov 29 '18 at 18:09
It helped because I realized that I had to do the BASE64 by myself. Then I used your url and it worked. Except that now you can not access backend directly, but that's not necessary.
– Paflow
Nov 29 '18 at 18:09
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53322226%2fpdf-download-in-href-of-a-element-results-in-empty-pdf%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
"since the PDF is definitely correct" - and how do you know this?
– Ryan McDonough
Nov 19 '18 at 10:30
As I wrote - I tested to call the backend directly with postman, and I wrote a pdf-file from backend on the servers harddrive, and in both cases it got a correct pdf with contents.
– Paflow
Nov 19 '18 at 13:29