I have a php file like this:
<?php
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"my-data.csv\"");
$data = stripcslashes($_REQUEST['data']);
echo $data;
?>
I can post (proper formatted) data to it and it will return a csv file. I do that like this:
var data = $('table').toCSV('tbody > tr');
$('table').addEvent('click', function(){
new Request({
url: 'getCSV.php',
method: 'post'
}).send('data=' + data);
});
In Firebug I can see the request works and the response is ok. But the Download dialog does not pop up; how to fix that? Do I need different headers in the PHP file?
As Gavin said, ajax calls cannot force download, and response is simply saved into a variable.
You must create a hidden form and POST data. Like this:
var data = $('table').toCSV('tbody > tr');
$('table').on('click', function(){
$('<form action="getCSV.php" target="_new" method="POST" style="display: none;">'+
'<textarea name="data">'+data+'</textarea>'+
'</form>')
.appendTo('body')
.submit();
});
P.S I haven't tested it.
I changed the JS to this:
var data = $('lijst').toCSV('tbody > tr');
var form = new Element('form', {method: 'post', action : 'getCSV.php'});
var field = new Element('input', {type: 'hidden', name: 'data', value: data});
var submit = new Element('input', {'type' : 'submit', 'value' : 'Download'});
form.adopt(field,submit);
form.inject($('lijst').getElement('caption'));
Which adds a nice download button to the table and as the browser follows a form submit, the download dialog pops up. Thanks for thinking with me.
Another way to do this is to utilize an iframe. So when clicking the "download" button you inject the iframe in the page. After you can clean it up.
document.body.inject(
new Element('iframe', {
'src': 'http://url.to.download',
'style': {
'display': 'none'
}
})
);
Related
My code works fine when I run the php script without ajax as a GET request. I get prompted to download the rendered pdf and all is well. However, I need to use ajax because I need to send more info from an html page to the php script than can be handled in a GET request.
What do I need to put into my ajax to make this work?
Thanks
js
function makePDF()
{
var x;
if(window.event) // IE8 and earlier
{
x=event.keyCode;
}
else if(event.which) // IE9/Firefox/Chrome/Opera/Safari
{
x=event.which;
}
keychar=String.fromCharCode(x);
alert(keychar);
if (keychar == 'p' || keychar == 'P')
{
var charSheetHTML = characterSheet.innerHTML;
$.ajax({
url: 'pdf.php',
data: {'charactersheet': charSheetHTML,},
type: 'post',
success: function (data) {**WHAT_DO_I_PUT_HERE??**},
error: function (data) { alert("error\n" + data.toString()); }
});
}
}
pdf.php
<?php
include_once( "bxcharacter/PDFChar.php.inc" );
PDFChar();
?>
PDFChar.hph.inc
<?php
require_once('./tcpdf/tcpdf.php');
function PDFChar(){
$pdf = new TCPDF();
$pdf->AddPage('P');
$pdf->writeHTML($_POST['charactersheet']);
$pdf->Output("character.pdf", 'D');
}
?>
This is not an ajax solution, but you can send your data with this way and if no error occurs, your page will not change.
Create a form element with inputs hidden which contains your data you want to send:
example format:
<form id="myForm" method="GET" action="pdf.php">
<input type="hidden" name="data1" type="hidden" value="your JSON.stringify() data">
</form>
js code (call these where your ajax request is):
var myForm = '<form id="myForm" method="GET" action="pdf.php">';
myForm += '<input type="hidden" name="data1" type="hidden" value="JSON.stringify() data">';
myForm += '</form>';
$("body").append(myForm); // temporarily appending
$("#myData-form").submit(); // submitting form with data
$("#myData-form").remove(); // remove form after submit
And as you said, force download will force file to download and page will remain same. However, if an error occurs, your page will change of course.
I don't know whether this is an effective way or not but in my case, this does the trick.
Old question, but I was trying to do something similar with Laravel PDF extension, and stumbled across this question. I did successfully do this asynchronously with the help of a nice blog post
https://nehalist.io/downloading-files-from-post-requests/
https://github.com/nehalist/download-post-requests
The using the form method, like the previous answer works fine too, but maybe this will help anyone else trying to achieve this with AJAX. The author's XMLHttpRequest method worked great for me!
The code that worked for me (almost verbatim from the blog post) ->
document.getElementById('exportpdf').addEventListener('click', function () {
var request = new XMLHttpRequest();
request.open('POST', '/your/post/endpoint/here', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.responseType = 'blob';
request.onload = function() {
if(request.status === 200) {
var disposition = request.getResponseHeader('content-disposition');
var matches = /"([^"]*)"/.exec(disposition);
var filename = (matches != null && matches[1] ? matches[1] : 'file.pdf');
var blob = new Blob([request.response], { type: 'application/pdf' });
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
};
I tried to get it to work with jQuery AJAX but failed, so I went with XMLHttpRequest. With jQuery, The download would work, but the content was always empty. I tried to do something like in this post -
https://keyangxiang.com/2017/09/01/HTML5-XHR-download-binary-content-as-Blob/
$.ajax does not support either arraybuffer or blob as its dataType. Thus we need write a beforeSend handler:
//setup ajax
$.ajaxSetup({
beforeSend:function(jqXHR,settings){
if (settings.dataType === 'binary'){
settings.xhr().responseType='arraybuffer';
settings.processData=false;
}
}
})
//use ajax now
$.ajax({
url:url,
dataType:"binary",
success:function(data){
console.log(data); //ArrayBuffer
console.log(new Blob([data])) // Blob
}
})
But never got it to work. Maybe someone smarter can figure out the jQuery method :)
I am trying to call a user defined function in jquery after ajax call,
function required to be called : downloadCurrentKey()
My requirement is after click of "generate_billing_key", function downloadCurrentKey() should automatically called, and when I click on label, at that time also function should be called.
It is working well in google chrome, but not in Mozilla Firefox.
Following is js code, Please guide me.
$(document).on('click', '#generate_billing_key', function(){
var url = $('#hdGenerateBillingKeyPair').val();
$.post(url, {
}, function (data) {
var obj = JSON.parse(data);
content="<label id='btn_download_billing_key'>
Click here to download key</label>";;
$("#newKeyDiv").html(content);
downloadCurrentKey();
});
});
$(document).on('click', '#btn_download_billing_key', function(){
downloadCurrentKey();
});
function downloadCurrentKey(){
var url=$('#hdDownloadBillingKeyPath').val();
my_form=document.createElement('FORM');
my_form.name='myForm';
my_form.method='POST';
my_form.action=url;
my_form.submit();
}
The code of url is as below
/**
* #Route("/downloadBillingKey",name="download_billing_key")
* #Template()
*/
public function downloadBillingKeyAction(Request $request) {
$file_name="key";
$file_content="";
header("Content-type: plain/text");
header("Content-Disposition: attachment; filename=$file_name.txt");
header("Pragma: no-cache");
header("Expires: 0");
echo $file_content;
die;
}
Thank you.
In this way, I reached the solution.
-Removed function downloadCurrentKey() from js file
-Added a form in twig file (instead of calling above function, I call submit event of this added function)
-code in controller remains same.
Code for js
$(document).on('click', '#generate_billing_key', function(){
var url = $('#hdGenerateBillingKeyPair').val();
$.post(url, {
}, function (data) {
var obj = JSON.parse(data);
content="<label id='btn_download_billing_key'>
Click here to download key</label>";;
$("#newKeyDiv").html(content);
$("#downloadFile").submit();
});
});
});
$(document).on('click', '#btn_download_billing_key', function(){
$("#downloadFile").submit();
});
Code for twig
<form method="post" action="{{ path('download_billing_key') }}" id="downloadFile" />
</form>
You didn't posted all of your code didn't you?
I'm telling that because I tried to simulate your code here and it only worked when I done this:
In your exemple, the js code you are posting nothing.
Everything after var obj = JSON.parse(data); (like the $("#newKeyDiv").html(content) appear only if exist data to parse.
On this line content="<label id='btn_download_billing_key'>Click here to download key</label>";; there is two ;
And maybe the most important is that maybe you should append the form in the page. Try this:
function downloadCurrentKey(){
var url=$('#hdDownloadBillingKeyPath').val();
// Get the element that will recive the form
my_tag=document.getElementById("someID");
my_form=document.createElement('FORM');
// Append the form in the page before you post
my_tag.appendChild(my_form);
my_form.name='myForm';
my_form.method='POST';
my_form.action=url;
my_form.submit();
}
Your page must have something like:
<p id="someID"></p>
I hope it helps you anyway.
This is my jQuery:
$( document ).ready(function() {
var instrID;
var cat;
$(window).load(function(){
});
$.post('ajax.php', {InstrumentID: instrID, catView: "pdf"}, function(data){
$('#displayPDF').append("<php> header('Content-type: application/pdf') </php>");
$('#displayPDF').append("<php> echo("+ data +") </php>");
});
This is my ajax or ajax.php:
<?php
include '../include/xxxxx.php';
$instrumentID = $_POST['InstrumentID'];
$category = $_POST['catView'];
$sql = "SELECT * FROM `xxxxx` WHERE `InstrumentID` = '" . $_POST['InstrumentID'] . "'";
$results = mysql_query($sql);
if($category == "pdf")
{
header("Content-type: application/pdf");
echo (mysql_result($results, 0, 'Instrument'));
}
?>
This is my div displayPDF It's empty:
<div id="displayPDF">
</div>
The jQuery and the div are in the same php file. I am wanting to display a pdf in the same page that the click event happens. Everything is working except for getting the pdf. When the pdf gets echoed to the div it just comes back as a bunch of characters. The pdf I am trying to display is less than 1 mb. Any ideas would be greatly appreciated.
Maybe this is not an answer to the specific question but, This question comes up at very first google search, so I would like to share my approach for downloading pdf when it's blob data.
$.ajax({
url: 'someurl',
method: 'get',
data: { param1: value1, param2: value2 },
xhr: function() {
const xhr = new XMLHttpRequest();
xhr.responseType= 'blob'
return xhr;
},
success: function (blob) {
const link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download="my-pdf-file-name";
link.click();
}
});
You haven't set a value for instrID, also you're not sanitizing for input.
Anyway instead of using ajax you can just embed the pdf into the page
var source = 'ajax.php?InstrumentID='+encodeUriComponent(instrID)+'&catView=pdf';
$('#displayPDF').append('<object data="'+source+'" type="application/pdf">'+
'<embed src="'+source+'" type="application/pdf"/></object>');
and then use $_GET instead of post in your php.
I don't think you can display a PDF inline in this manner. Try switching to an iframe - that should work. That is set the location of the iframe to your ajax.php.
New here and glad to be, I've gotten a lot of answers from this forum. I am however stuck at the moment.
I have some javascript that is creating a window color and handle picker (click on the color swatch it changes the image, click on a handle and it does the same). Below the image is a description of the window selected. This text is being generated by the javascript by pulling the image titles.
Now the fun part. Below this picker I need to add a form that will be emailed using php. Within that email I need to pull the window description that is being generated by the javascript.
I have tried so many things today I have lost count. The last bit of code I tried was
<script>
$(document).ready(function() {
$("windowDesc").each(function() {
var html = jQuery(this).html();
});
});
</script>
And in the php mail file I added:
$windowtitle = $_GET['html'];
as well as trying
$windowtitle = $_POST['html'];
and I have also tried the following:
<script>
var content = $('#windowDesc').html();
$.ajax({
url: 'send_mail.php',
type: 'POST',
data: {
content: content
}
});
</script>
And in the php mail file I added:
$windowtitle = $_GET['content'];
as well as trying
$windowtitle = $_POST['content'];
Not to mention a plethora of other things.
Basically what I am trying to do is grab the content of the div that holds the generated text and email it. If any of the above are correct then I must be placing them in the wrong position or something. With the first one I have tried it inside the form, outside the form, before the div, after the div. Just haven't tried it on top of my head yet. It's been a long day, thanks in advance :o)
Sorry for the delay, been a busy two days. OK, so here is the code that handles the window color and handle picker:
var Color = "color";
var Handle = "handledescription";
var ColorDesc = "color";
var HandleDesc = "handle description"
function Window(Color,Handle,ColorDesc,HandleDesc) {
$('#windowPic').animate({opacity: 0}, 250, function () {
thePicSrc = "http://www.site.com/images/windows/" + Color + Handle + ".jpg";
$('#windowPic').attr('src', thePicSrc);
$('#windowDesc').html("<p>" + ColorDesc + " frame with " + HandleDesc + " hardware</p>");
$('#windowPic').animate({opacity: 1}, 250)
})
}
$(document).ready(function() {
$('#wColors li').click( function() {
Color = $(this).attr('id');
ColorDesc = $(this).attr('title');
Window(Color,Handle,ColorDesc,HandleDesc);
});
$('#wHandles li').click( function() {
Handle = $(this).attr('id');
HandleDesc = $(this).attr('title');
Window(Color,Handle,ColorDesc,HandleDesc);
});
});
You need a hidden input in your form:
<form id="send_email" action="send_email.php">
<input id="content" type="hidden" name="content"/>
... other inputs here
</form>
Then you can use Javascript to fill it in before submission:
$("#send_email").submit(function() {
$("#content").val($("#windowDesc").html());
}
<script>
var content = $('#windowDesc').html();
$.ajax({
url: 'send_mail.php',
type: 'POST',
data: content
});
</script>
It worked here.
I have been trying to create a simple calculator. Using PHP I managed to get the values from input fields and jump menus from the POST, but of course the form refreshes upon submit.
Using Javascript i tried using
function changeText(){
document.getElementById('result').innerHTML = '<?php echo "$result";?>'
but this would keep giving an answer of "0" after clicking the button because it could not get values from POST as the form had not been submitted.
So I am trying to work out either the Easiest Way to do it via ajax or something similar
or to get the selected values on the jump menu's with JavaScript.
I have read some of the ajax examples online but they are quite confusing (not familiar with the language)
Use jQuery + JSON combination to submit a form something like this:
test.php:
<script type="text/javascript" src="jquery-1.4.2.js"></script>
<script type="text/javascript" src="jsFile.js"></script>
<form action='_test.php' method='post' class='ajaxform'>
<input type='text' name='txt' value='Test Text'>
<input type='submit' value='submit'>
</form>
<div id='testDiv'>Result comes here..</div>
_test.php:
<?php
$arr = array( 'testDiv' => $_POST['txt'] );
echo json_encode( $arr );
?>
jsFile.js
jQuery(document).ready(function(){
jQuery('.ajaxform').submit( function() {
$.ajax({
url : $(this).attr('action'),
type : $(this).attr('method'),
dataType: 'json',
data : $(this).serialize(),
success : function( data ) {
for(var id in data) {
jQuery('#' + id).html( data[id] );
}
}
});
return false;
});
});
The best way to do this is with Ajax and jQuery
after you have include your jQuery library in your head, use something like the following
$('#someForm').submit(function(){
var form = $(this);
var serialized = form.serialize();
$.post('ajax/register.php',{payload:serialized},function(response){
//response is the result from the server.
if(response)
{
//Place the response after the form and remove the form.
form.after(response).remove();
}
});
//Return false to prevent the page from changing.
return false;
});
Your php would be like so.
<?php
if($_POST)
{
/*
Process data...
*/
if($registration_ok)
{
echo '<div class="success">Thankyou</a>';
die();
}
}
?>
I use a new window. On saving I open a new window which handles the saving and closes onload.
window.open('save.php?value=' + document.editor.edit1.value, 'Saving...','status,width=200,height=200');
The php file would contain a bodytag with onload="window.close();" and before that, the PHP script to save the contents of my editor.
Its probably not very secure, but its simple as you requested. The editor gets to keep its undo-information etc.