Reputation: 876
I have a PHP script that accepts a $_POST
variable to trigger a PDF file download, and that script is already set to return the file as a download rather than load the file in-browser or save the file to the server.
I can get this file to download with a simple form, no problems at all, however as there is about 5 to 10 seconds of processing time I decided to try and have jQuery handle the click
event so that I could display a "Please Wait" message while the script is processed and a "File download has started" message when the processing is complete, which as it turns out is much more difficult that I'd hoped for.
I can get the click
to display the "Please Wait" message, but then can't identify when the page has finished processing so the "Please Wait" message remains even after the PDF is downloaded.
If I use jQuery to handle the click
event and POST
the data with ajax
, using preventDefault
, I get the correct "Wait" and "Download Started" messages, but can't return the file download to the browser.
I've temporarily incorporated both methods by not using preventDefault
, which to the user is the exact behaviour that I want: it shows "Please Wait" until the file download starts and then "File download has started" when the file actually begins to download. However, as I'm sure is obvious, this is actually posting the data twice: once with the form
and the other with jQuery
, and as they take the same amount of time to complete the request the functionality I want is achieved.
Is there a way to do achieve what I want properly?
HTML Form ($filename
is from the database call)
<form method="post" action="pdf/index.php" name="pdfForm" id="pdfForm">
<button type="submit" class="downloadButton"
name="filename" value="'.$filename.'">'.$filename.'</button>
</form>
"Working" jQuery (there is some redundancy from other versions I've tried, sorry)
<script>
$(document).ready(function() {
$('.downloadButton').on('click', function(e) {
//e.preventDefault(); // File will not download if this is not commented out
var $filename = $(this).val();
var $thisBox = $(this);
var $url = $('#pdfForm').attr('action');
$thisBox.text("Please Wait");
url = $url;
return $.post(url, {filename: $filename})
.done(function(data) {
$thisBox.text("File Download has started");
// This won't happen unless e.preventDefault() is excluded
});
});
});
</script>
I've trawled countless other questions hoping for a solution, but found nothing that works for me. The closest I got was with ajax
blob
, but I need support for older browsers and the results weren't great anyway.
Any help would be greatly appreciated, hopefully I'm just missing something obvious and now can't see it having looked at it for so long.
Upvotes: 0
Views: 1388
Reputation: 505
I had the same problem for a word and I found the solution. Maybe you should modify for a pdf maybe not.
//When click...
//For browers doesn't support the download attribut....
//The only issue is to past by a popup with the GET method
a = document.createElement('a');
if(typeof a.download =="undefined") {
win = window.open('your_url?data=data','_blank','height=200,width=200,left=10,top=10,resizable=yes,scrollbars=yes,toolbar=yes,menubar=no,location=no,directories=no,status=yes');
var loop = setInterval(function() {
if(win.closed) {
clearInterval(loop);
//Hide your modal or clean your innerhtml here
}
}, 1000);
return(false);
}else{
// Use XMLHttpRequest
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
var a;
if (xhttp.readyState === 4 && xhttp.status === 200) {
a.href = window.URL.createObjectURL(xhttp.response);
a.download = "name_file";
a.style.display = 'none';
document.body.appendChild(a);
a.click();
}
};
xhttp.open("POST", 'your_url');
xhttp.setRequestHeader("Connection", "close");
xhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// For a word I must return a 'blob' because it's a binary. Maybe you should change it
xhttp.responseType = 'blob';
xhttp.send(JSON.stringify(your_data));
xhttp.addEventListener('readystatechange', function() {
if (xhttp.readyState === XMLHttpRequest.DONE) {
//Hide your modal, or clean your innerhtml here
}
});
}
Upvotes: 1