I want to achieve:
in a html-form put in some data (e.g. -wahl- and -id- )
after klicking -submit- call the javascript function -machExport-
this function validates the values and passes them (-wahl- and -id-) to the php-File -makeExport.php-
the -php-Funktion gets these values, gets some data from a mysql database, creates output-data,
writes these data into a file -data.txt- and download this file instantly to the users download-folder.
Everything works quite well, but:
after creating the data, this data is stored into the file but there is no downloading.
So, what's wrong.
(If I execute the -php-file directly by passing some values to the php-function, it works quite well,
so only if there ist the javascript function between the html- and the php-function, ist doesn't work )
Part of the code within my -html- document
<form name="form" action="" method="post" onsubmit="return machExport()" onreset="abbruch()">
Javascript-Code:
function machExport(){
var wahl = $("input[name='rd1']:checked").val();
var id = $("#id").val();
// verify these values and give an error message, if necessary
...
// if everything is ok, pass values to the -php- function
var ajxFile = 'makeExport.php';
var param = wahl + "#" + id;
$.ajax({
type: "POST",
url: ajxFile,
data: param
// if I put here a -success: function -statement,
// then the data having been created within my php-function
// is not beeing written into the requested file
// but is displayed in my html-document.
}
});
return false;
}
PHP-File -makeExport.php-
<?php
// get the values for -wahl- and -id-
...
// create data to write into file
$data = ...
// write data to file and download this file instantly
$file = "data.txt";
$fOK = file_put_contents ( $file , $data );
// up to here, it works
// but the next 3 lines are not excecuted
header("Content-Type: text/plain");
header("Content-Disposition: attachment; filename=\"$file\"");
readfile($file);
?>
Related
I am struggling with achieving what I want and am not sure if it is possible. I am using CodeIgniter and PHP for my web application. My home view allows users to query a database and the results are generated and displayed in the table form on the page. The user will then review the table and be provided the option of downloading as an xlsx Excel file. I am using an ajax post to send the table data to my PHP controller that will create the Excel file. I also need this to work in all browsers especially Safari, as the client will access the application from Ipads as well as desktop machines.
My home ajax post: (t is the id of the generated table)
$("#btnExport").click(function() {
$.ajax({
type: "POST",
url: '<?php echo base_url();?>index.php/Home/excel',
datatype: 'html',
data: {
'queryData': $("#t").html()},
success: function (response) {
alert(response);
}
});
});
My controller function:
public function excel()
{
$this->load->library('excel');
$filename = "data";
$table = $this->input->post('queryData');
$objPHPExcel = new PHPExcel();
$tmpfile = time().'.html';
file_put_contents($tmpfile,$table);
$objReader = PHPExcel_IOFactory::createReader('HTML');
$objPHPExcel = $objReader->load($tmpfile);
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename='.$filename);
header('Cache-Control: max-age=0');
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter->save('php://output');
unlink($tmpfile);
}
The problem is the handling of the ajax response I've read its impossible to download a file from ajax. Everything I have tried is not working The response is binary encoded data I am assuming is the excel file. Is there a workaround to this problem? I decided on ajax as the table can change dynamically given the current query, and needs to be sent to the server accordingly.Thanks for any assistance.
EDIT
In the linked question it is about submitting forms and not triggering a download. I am not submitting any forms, just passing an html table to the PHP to build the Excel file. I fail to see how that is relevant to my problem. Am I misunderstanding?
Submitting a form is the best you can do to trigger a file download...
It's better to create one even if you don't have a form.
var baseUrl = '<?php echo base_url();?>'
var $form = $(`<form method="post" hidden action="${baseUrl}index.php/Home/excel"><textarea name="queryData">`)
$form.find('textarea').val($("#t").html())
$form.appendTo('body').submit()
There is however one alternative to saving ajax responses and that is by creating a link with a object url from a blob response, setting the download attribute and trigger a click (in IE you need to call navigator.saveOrOpenBlob)
There is a good lib out there that is called FileSaver to abstract out all nasty vendor specifics
The way you would use it is by doing this:
fetch(url, {method: 'post', body: data})
.then(res => {
var cd = res.header.get('Content-Disposition')
var filename = cd.match(/filename="(.+)"/)[1]
return res.blob().then(blob => saveAs(blob, filename))
})
But it's not as good as submitting a form and getting a bit of help from a server that can send a Content-Disposition header cuz not all browser (safari mainly) supports download attribute in links...
there are 2 possibilities that i know
1. store the constructed table in localStorage of your browser
<div id="myTable">
<table>
<tr>
<th>A</th>
<th>B</th>
</tr>
<tr>
<td>Value for column A</td>
<td>Value for column B</td>
</tr>
</table>
</div>
// in jquery
$(document).ready(function(){
alert('nothing');
if (typeof(Storage) !== "undefined") {
// Code for localStorage/sessionStorage.
var table = $('#myTable').html();
localStorage.setItem("storedTable",table);
} else {
console.log('no support');
// Sorry! No Web Storage support..
}
});
// now you can get the table in the next page like this
var table = localStorage.getItem("storedTable");
2. solution, store them in the $_SESSION like this
session_start()
$_SESSION["myTable"] = $yourConstructedTable
redirect to that page where you want to print
get the table like so
session_start();
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
$table = $_SESSION["myTable"];
unset($_SESSION["myTable"]); // don't forget to unset the session
// rest of your code
I have this script in a .html file on my page and im trying to just run the getip.php file from here rather than to rename the file to .php. I tried this ajax call but its not working and not logging the ip in the logfile.txt. Please let me know what I am doing wrong.
Ajax in the head of the .html file:
<script>
$(document).ready(function() {
$.ajax({
type: "GET",
url: "getip.php",
}); // Ajax Call
}); //event handler
</script>
Code from getip.php:
<?php
// location of the text file that will log all the ip adresses
$file = 'logfile.txt';
// ip address of the visitor
$ipadress = $_SERVER['REMOTE_ADDR'];
// date of the visit that will be formated this way: 29/May/2011 12:20:03
$date = date('d/F/Y h:i:s');
// name of the page that was visited
$webpage = $_SERVER['SCRIPT_NAME'];
// visitor's browser information
$browser = $_SERVER['HTTP_USER_AGENT'];
// Opening the text file and writing the visitor's data
$fp = fopen($file, 'a');
fwrite($fp, $ipadress.' - ['.$date.'] '.$webpage.' '.$browser."\r\n");
fclose($fp);
?>
Have you tried $.post() function instead? Example:
<script>
$(document).ready(function() {
$.post('getip.php'); // Ajax Call
}); //event handler
</script>
You can also add a callback as a second parameter.
I would use the full URL for the ajax call. Depending on your framework you might not be hitting the intended endpoint. You could try echo 'test'; in your php file and adding a done handler to your ajax call to make sure you're hitting the php file in the first place:
.done(function( data ) {
alert(data);
});
I have a nginx rewrite rule that redirects an img src attribute to a php page. Within this php page I'm trying make a GET request, which on success makes a POST request to the same page, sending the data returned from the GET request as the data. Why is the $_POST data empty in the php script? If I hardcode $name = "http://path/to/my/img.png" in the php script the image renders correctly.
<?php
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);
var_dump($_REQUEST);
//if(isset($_POST['val'])) {
// open the file in a binary mode
$name = $_POST['val']; // ALWAYS EMPTY
$fp = fopen($name, 'rb');
// send the right headers
header("Content-Type: image/png");
header("Content-Length: " . filesize($name));
// dump the picture and stop the script
//echo fpassthru($fp);
header("Location: $name");
exit;
//}
?>
<html>
<head>
<script type='text/javascript' src='/steal/steal.js'></script>
<script type="text/javascript" src="/plugins/jquery/json2.js"></script>
<script type="text/javascript">
steal('jquery/dom/fixture').then(function(){
$.fixture("GET /event/{code}", function(original, settings, headers){
return [200, "success", { "img_url":"http://path/to/my/img.png" }, {} ]
})
var strObj = <?php echo json_encode($_REQUEST); ?>;
var str = strObj.q;
var eventCode = str.split('/')[1];
$.ajax({
url: "/event/"+eventCode,
success: function(data) {
var imgUrl = data.img_url
$.ajax({
type: 'POST',
contentType: 'json',
data: {val:imgUrl},
success: function(data){
console.log(data);
},
error: function(jqXHR, textStatus, errorThrown){
console.log(textStatus);
}
});
}
});
});
</script>
</head>
<body>
</body>
</html>
Alright, you've taken things a few steps beyond what is possible.
When the user hits this image in their email, a request is sent to your server asking for that image. None of that javascript is going to make it back to the user because the <img> tag is expecting an image, not an html document. You can tack things on to the outgoing request via something like
<img src="http://yourwebsite.com/tracker.php?val=someimage.png">
and your script will be able to get val out of $_GET but you won't be able to make a POST request for this image from inside an email.
All that $_REQUEST data you're getting at the top there? That's where you get all your email tracking data from. Everything you can get out of there and $_GET is all you're getting.
Afterwards, you need to give them back an image. So heres how you do that.
$val = $_GET['val']; // assuming val contains an image
header('Content-Type: image/png');
readfile('/path/to/your/images/'. $val);
Please be super aware that you need to sanity check $val to make sure its only containing images that you want to be able to see. A potentially malicious user could see this and put something like tracker.php?val=/etc/passwd or something similar and then you've got PHP trying to read your password file. Making sure that images exist and can even be read can be done with the is_readable() function.
I need to generate a PDF file with some information i get from a database, i'm using PHPExcel in order to do this, but here is the thing, when i click the button `report` so i get all the information and put it into the PDF, i get a lot of "garbage" in my page, this garbage it's like when you try to open a PDF with notepad and it just shows random symbols.
Here is how i do it
I'm using an $.ajax call to get all the information displayed into a form:
$.ajax({
// gets all the information and puts them into the form and several tables
});
Then i add an event handler to the button report so that i send the request id to a php script which will gather the necessary information to fill the report
report.on('click',function(){
$.ajax({
url : '../../php/reports/requestReport.php',
type : 'post',
data : {'idRequest' : id },
dataType : 'json',
success : function(response){
console.log(response);
},
error : function(response){
if(response.responseText != undefined)
$('body').append(response.responseText);
console.warn(response);
}
});
});
And on my php file i have something like this:
<?php
require '../functions.php';
require '../classes/PHPExcel.php';
if(isset($_POST['idRequest']))
$idRequest = $_POST['idRequest'];
else{
$idRequest = false;
echo json_encode(array("ExitCode"=>1,"Message"=>"idRequest Not Received","Location"=>"requestReport.php"));
}
if($idRequest){
try{
// get all the data
// save the request and send it to the report
$excel = new PHPExcel();
//Initializing
$excel->getProperties()->setCreator("TTMS")
->setLastModifiedBy("TTMS")
->setTitle("Request update $idRequest");
$excel->setActiveSheetIndex(0)
->setCellValue('C1', 'Request For Q.A. / Q.C. / Testing');
// Rename worksheet
$excel->getActiveSheet()->setTitle("$idRequest");
// Set active sheet index to the first sheet, so Excel opens this as the first sheet
$excel->setActiveSheetIndex(0);
// Redirect output to a client’s web browser (PDF)
header('Content-Type: application/pdf');
header('Content-Disposition: attachment;filename="Update_Request_'.$idRequest.'.pdf"');
header('Cache-Control: max-age=0');
$objWriter = PHPExcel_IOFactory::createWriter($excel, 'PDF');
$objWriter->save('php://output');
} catch(PDOException $ex){
echo json_encode(array("ExitCode"=>2,"Message"=>$ex->getMessage(),"Location"=>"requestReport.php PDOException"));
}
So long story short i get garbage on the page where the form is. I think it has something to do with the fact that i'm doing this via ajax but i need to do this so the echo's i have to report the errors in my code.
You're writing the PDF output inside an existing HTML page
$('body').append(response.responseText);
The browser assumes everything displayed in an HTML page is HTML markup, not a stream of binary data.
Direct the output to a new browser window if success.
Write all the output to an HTML file, then use wkhtmltopdf -> http://code.google.com/p/wkhtmltopdf/ to convert it to PDF. It works awesome!
Here is code you would use to create your html file:
if (!$handle = fopen('/path/to/folder/your_file.html', 'w')) {
die("Cannot open file for write");
}
$data_string = "<html><body></body></html>"; //all your html output goes here, formatted correctly, etc
// Write somecontent to our opened file.
if (fwrite($handle, $data_string) === FALSE) {
die("Cannot write to file");
}
Then once that is successful you convert it to PDF, then remove the old html file
// convert to PDF
$output = shell_exec('wkhtmltopdf --page-size Letter /path/to/folder/your_file.html /path/to/folder/your_file.pdf');
if (strpos($output,'Error') == false){
$output = shell_exec('rm /path/to/folder/your_file.html');
}else{
die("error creating pdf, please contact IT administrator.");
}
Now you have the PDF sitting in the location -> /path/to/folder/your_file.pdf which you can make the user download.
I have the following code in my index.php page:
// Write the resulting JSON to a text file
var jsontext = $('#code-output').text();
$.ajax({
url: 'writetxt.php',
type: 'POST',
data: { data: jsontext },
success: function(result) {
$('#code-output').hide().fadeIn('slow');
}
});
And this is the contents of writetxt.php:
// Generating a unique filename using the date and time plus a random 4-digit string
$filename = date("YmdHis-") . rand(1337,9001);
// Making the JSON text file
$jsontext = $_POST["data"];
$fp = fopen("jsontxt/" . $filename . ".txt","w");
fwrite($fp,$jsontext);
fclose($fp);
Basically, a new text file is created every time a change is made to the JSON text. How do I access $filename from the index.php file?
Either include the file in the other one
require_once('my_file.php');
echo $varFrom_my_file;
or set it to a session variable
session_start();
$_SESSION['foo'] = "Bar";
Then the other file
echo $_SESSION['foo'];
I'm assuming index.php has some content along with PHP variable? Using include will include that content. Use a session variable to go across pages.
PHP Sessions
Return the value of $filename as a JSON string
echo json_encode(array('filename'=>$filename);
Then pull it out of the result var
result.filename
(untested)