Generating Files with JavaScript and PHP - javascript

I am trying to generate a file to download. With JavaScript I call a PHP file to process my request and send back the result in a way it should be possible to download it. But instead of making it available for download it simply display the code.
PHP
function export()
{
// Get a database object.
$db = JFactory::getDbo();
// Create a new query object.
$query = $db->getQuery(true);
// Select fields to get.
$fields = array(
$db->quoteName('params')
);
// Conditions for which records should be get.
$conditions = array(
$db->quoteName('element') . ' = ' . $db->quote('plugin_name'),
$db->quoteName('folder') . ' = ' . $db->quote('system')
);
// Set the query and load the result.
$query->select($fields)->from($db->quoteName('#__extensions'))->where($conditions);
$db->setQuery($query);
$results = $db->loadResult();
// Namming the filename that will be generated.
$name = 'file_name';
$date = date("Ymd");
$json_name = $name."-".$date;
// Clean the output buffer.
ob_clean();
echo $results;
header('Content-disposition: attachment; filename='.$json_name.'.json');
header('Content-type: application/json');
}
JavaScript
function downloadFile() {
var fd = new FormData();
fd.append('task', 'export');
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", uploadComplete, false);
xhr.open("POST", "my_php_file");
xhr.send(fd);
}
HTML file
<button class="btn btn-primary btn-success" type="button" onclick="downloadFile()"></button>
UPDATE MY CODE

You need to call any header function calls before you output data. Otherwise you will get a headers "Headers already sent" warning, and the headers will not be set.
Example:
...
// Namming the filename that will be generated.
$name = 'file_name';
$date = date("Ymd");
$json_name = $name."-".$date;
header('Content-disposition: attachment; filename='.$json_name.'.json');
header('Content-type: application/json');
// Clean the output buffer.
ob_clean();
echo $results;

An example
<?php
ob_start();
echo "some content to go in a file";
$contentToGoInFile = ob_get_contents(); //this gets the outputted content above and puts it into a varible/buffer
ob_end_clean();
header('Content-disposition: attachment; filename='.$json_name.'.json');
header('Content-type: application/json');
echo $contentToGoInFile;
exit; //stops execution of code below
example with your code
$results = $db->loadResult();
// Namming the filename that will be generated.
$name = 'file_name';
$date = date("Ymd");
$json_name = $name."-".$date;
ob_start();
echo $results;
$contentToGoInFile = ob_get_contents(); //this gets the outputted content above and puts it into a varible/buffer
ob_end_clean();
header('Content-disposition: attachment; filename='.$json_name.'.json');
header('Content-type: application/json');
echo $contentToGoInFile;
exit

Related

header function filename is not working in PHP

header function filename is not working in PHP. I try to export a CSV file but it always downloads the page name only like export.php
I try so many codes and force download. but I can't. plz anyone help me
enter code here
if(isset($_POST["export"]))
{ include 'database/config.php';
include "database/database.php";
$db = new database();
$fn = "csv_".uniqid().".csv";
$file = fopen($fn, "w");
$query = "SELECT * from wp_terms";
$read = $db -> select($query);
fputcsv($file, array('ID', 'Name', 'slug', 'term group'));
if($read) {
while ($row = $read->fetch_assoc()) {
fputcsv($file, $row);
}
}
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="'.$fn);
fclose($file);
}
This will perfectly work for me so try following code.
add_action("admin_init", "download_csv");
function download_csv() {
if (isset($_POST['download_csv'])) {
global $wpdb;
$sql = "SELECT `sub_email` FROM `wp_terms`";
$rows = $wpdb->get_results($sql, 'ARRAY_A');
if ($rows) {
$csv_fields = array();
$csv_fields[] = "first_column";
$csv_fields[] = 'second_column';
$current_date = date("Y-m-d");
$output_filename = 'subscriber_list'.$current_date.'.csv';
$output_handle = #fopen('php://output', 'w');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Description: File Transfer');
header('Content-type: text/csv');
header('Content-Disposition: attachment; filename=' .
$output_filename);
header('Expires: 0');
header('Pragma: public');
$first = true;
// Parse results to csv format
foreach ($rows as $row) {
// Add table headers
if ($first) {
$titles = array();
foreach ($row as $key => $val) {
$titles[] = $key;
}
fputcsv($output_handle, $titles);
$first = false;
}
$leadArray = (array) $row; // Cast the Object to an array
// Add row to file
fputcsv($output_handle, $leadArray);
}
//echo 'test';
// Close output file stream
fclose($output_handle);
die();
}
}
}

How to use flatbuffer generated data in browser?

I'm trying to use flatbuffer in one of my web application. I've already stored those buffer data in one file (buffer_content.txt) by using following php code.
// ...Code to store to disk or send over a network goes here...
$file = 'buffer_content.txt';
$output = serialize($builder->dataBuffer());
$fp = fopen($file, "w");
fwrite($fp, $output);
fclose($fp);
Through ajax I can get the buffer data from the server. Now I need to extract the original data from that buffer in JavaScript. But, I can't able to fig out how to do that.
Any idea, how to do this ?
After referring Aardappel answer I did following changes in my code to solve this problem.
Create buffer file
$file = 'buffer_content.bin';
$output = $builder->dataBuffer();
$fp = fopen($file, "wb");
fwrite($fp, $output);
fclose($fp);
Code for getting buffer content from file & response back to ajax call
<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
// change these to whatever is appropriate in your code
$my_place = "/path/to/the/file/"; // directory of your file
$my_file = "item.bin"; // your file
//$my_path = $my_place.$my_file;
$my_path = $my_file;
header("Pragma: public");
header("Expires: 0");
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: pre-check=0, post-check=0, max-age=0', false);
header('Last-Modified: '.gmdate('D, d M Y H:i:s') . ' GMT');
$browser = $_SERVER['HTTP_USER_AGENT'];
if(preg_match('/MSIE 5.5/', $browser) || preg_match('/MSIE 6.0/', $browser))
{
header('Pragma: private');
// the c in control is lowercase, didnt work for me with uppercase
header('Cache-control: private, must-revalidate');
// MUST be a number for IE
header("Content-Length: ".filesize($my_path));
header('Content-Type: application/x-download');
header('Content-Disposition: attachment; filename="'.$my_file.'"');
}
else
{
header("Content-Length: ".(string)(filesize($my_path)));
header('Content-Type: application/x-download');
header('Content-Disposition: attachment; filename="'.$my_file.'"');
}
header('Content-Transfer-Encoding: binary');
if ($file = fopen($my_path, 'rb'))
{
while(!feof($file) and (connection_status()==0))
{
print(fread($file, filesize($my_path)));
flush();
}
fclose($file);
}
?>
Code for Parsing binary data at client side
var xhr = new XMLHttpRequest();
xhr.open('GET', 'getBufferData.php', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
// response is unsigned 8 bit integer
var responseArray = new Uint8Array(this.response);
var buf = new flatbuffers.ByteBuffer(responseArray);
var monster = MyGame.Sample.Monster.getRootAsMonster(buf);
var hp = monster.hp();
var pos = monster.pos();
console.log("hp : "+hp);
console.log("pos : "+pos);
};
xhr.send();
You don't want to use serialize. the dataBuffer already contains serialized data, check out what it says here:
https://google.github.io/flatbuffers/flatbuffers_guide_tutorial.html
$buf = $builder->dataBuffer(); // Of type Google\FlatBuffers\ByteBuffer
// The data in this ByteBuffer does NOT start at 0, but at buf->getPosition().
// The end of the data is marked by buf->capacity(), so the size is
// buf->capacity() - buf->getPosition().
Make sure you write the file in binary mode (pass "wb" to fopen). Also don't call it .txt since it isn't a text format :)
Then in JS, you read in the file (again, in binary mode, not text), make sure it ends up in a Uint8Array, then follow the code here: https://google.github.io/flatbuffers/flatbuffers_guide_use_javascript.html

Download (forcing Save As dialog) after using AJAX $.post

I have a webapp that simulates a terminal. Every command is posted via AJAX using the following script (portion):
AJAX/jQuery
$.post("sec/cmd_process.php", { n : n } )
.done(function(data){
output.append(display(data));
});
If the user types download log into the terminal, the following script - on sec/cmd_process.php is executed:
PHP
if(isset($_POST['n'])){
echo $_POST['n'];
$t = explode(' ', $_POST['n']);
if(strtolower($t[0])=='download'){
if(!isset($t[1])) shout_error("No download specified");
//Download Log
elseif($t[1]=='log'){
$stmt = $dbh->prepare("SELECT * FROM `tap_log` ORDER BY `time`");
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($rows as $row) {
$user = user_by_id($row['user']);
$data.= "{$row['time']} - User {$user['id']} ({$user['name1']} {$user['name2']}) - {$row['information']} ({$row['subject']})".PHP_EOL;
}
$handle = fopen('log.txt','w+');
fwrite($handle, $data);
$path = 'log.txt';
header('Content-Transfer-Encoding: binary');
header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($path)).' GMT');
header('Accept-Ranges: bytes');
header('Content-Length:'.filesize($path));
header('Content-Encoding: none');
header('Content-Disposition: attachment; filename='.$path);
readfile($path);
fclose($handle);
}
}
}
What I want to happen is for the generated file, log.txt, is downloaded via the Save As... dialog. This code works if you directly visit a PHP page with those headers, but how can I make it work through jQuery/AJAX?
The simplest solution I found was to return a <script> tag forwarding the location to a forced download page:
<script type='text/javascript'>
location.href='sec/download.php?file=log.txt&type=text';
</script>
sec/cmd_process.php
$handle = fopen('log_'.time().'.txt','w+');
fwrite($handle, $data);
echo "Please wait while the file downloads...";
echo "<script type='text/javascript'>location.href='sec/download.php?file=log.txt&type=text';</script>";
fclose($handle);
sec/download.php
<?php
$filename = $_GET['file'];
$filetype = $_GET['type'];
header("Content-Transfer-Encoding: binary");
header("Last-Modified: ".gmdate('D, d M Y H:i:s',filemtime($filename))." GMT");
header("Accept-Ranges: bytes");
header("Content-Length: ".filesize($filename));
header("Content-Encoding: none");
header("Content-Type: application/$filetype");
header("Content-Disposition: attachment; filename=$filename");
readfile($filename);

Server Sent Events : Not working

I am using HTML5 Server-Sent Events.
Actually I need to show notification (new record enter and which are unread) that's when any new record is insert in database (php/mysql).
So for testing purpose I just tried with count of total row. But I am getting this error message in my local-host:
Firefox can't establish a connection to the server at http://localhost/project/folder/servevent/demo_sse.php.
The line is:
var source = new EventSource("demo_sse.php");
I have tried this:
index.php
<script>
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("demo_sse.php");
source.onmessage = function(event) {
document.getElementById("result").innerHTML = event.data;
};
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
</script>
<div id="result"></div>
demo_sse.php
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$db = mysql_connect("localhost", "root", ""); // your host, user, password
if(!$db) { echo mysql_error(); }
$select_db = mysql_select_db("testdatase"); // database name
if(!$select_db) { echo mysql_error(); }
$time = " SELECT count( id ) AS ct FROM `product` ";
$result = mysql_query($time);
$resa = mysql_fetch_assoc($result);
echo $resa['ct'];
flush();
?>
Please let me know what going wrong.
I know for notification we can use Ajax with some interval time, but I don't want such thing. As I have N number of records and which may slow my resources.
According to this,
There are several 'rules' that need to be met, and yours is lacking at this point:
Output the data to send (Always start with "data: ")
It is somehow like:
echo "data: {$resa['ct']}\n\n";
Setting a header to text/event-stream worked for me:
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
// Rest of PHP code
Please modify the following code snippet according to your requirements
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
// infinite loop
while (1) {
// output the current timestamp; REPLACE WITH YOUR FUNCTIONALITY
$time = date('r');
echo "data: Server time: {$time}\n\n"; // 2 new line characters
ob_end_flush();
flush();
sleep(2); // wait for 2 seconds
}
?>
I tested this code snippet myself; it's working for me. If you have any query, let me know.

In PHP, I encoded a JSON array from mySQL . i want to decode it in different php file

In Php, I encoded a JSON array from MySQL table . i want to decode it in different Php file . and i want to access the data through JavaScript from different file. anyone please help me.
MY code is:
$serverName = "(local)";
$connectionInfo = array( "Database"=>"sample");
$conn = sqlsrv_connect( $serverName, $connectionInfo);
if( $conn )
{
echo "Connection established.<br/>";
}
else
{
echo "Connection could not be established.<br/>";
die( print_r( sqlsrv_errors(), true));
}
$str="Select * from sam1";
$res=sqlsrv_query($conn,$str) or die("Error !");
$response=array();
while( $row = sqlsrv_fetch_array( $res, SQLSRV_FETCH_ASSOC) )
{
$response['tdata'][]=$row;
}
print(json_encode($response));
Output is :
{"tdata":[{"id":"1","name":"aaa"},{"id":"2","name":"bbb"},{"id":"3","name":"ccc"}]}
My decode Function is:
$data = file_get_contents('db2.php');
$data1 = json_decode($data, true);
print($data1);
but its not working..
When you return JSON encoded string it is best if you send a proper headers. You should return JSON like that (you can still use print function):
<?php
header('Content-Type: application/json');
echo json_encode($data);
Now, when you retrieve this output, send it to json_decode function that will return an object.
json_decode.
file_get_contents function retrieves content of the file, it does not parse it. To retrieve the content of the file:
by calling it with an URL (DO NOT USE THIS ONE I am showing this method for the purpose of learning only, this function wont load URL if allow_url_fopen directive is off, instead you can use curl library (here))
$json = file_get_contents('www.example.com/db2.php');
echo json_decode($json, true);
by including it with a relative path
$json = (include "db2.php");
echo json_decode($json, true);
in this particular scenario, db2.php has to use return statement like so
return json_encode($response);
by using ob_* with include, this time you do not need to return in db2.php file
ob_start();
include "db2.php";
$json = ob_get_contents();
ob_end_clean();
echo json_decode($json, true);
It looks like you're populating $data with the text of db2.php instead of the output from running the file in php. Try this:
$data = `php db2.php`

Categories

Resources