I am new to server-sent-events and copied the tutorial example from the w3 site.
The html page:
<html>
<body>
<div id="result"></div>
<script>
var source = new EventSource("sse.php");
source.onmessage = function(event) {
document.getElementById("result").innerHTML = event.data + "<br>";
};
</script>
</body>
</html>
The php script:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$time = date('r');
echo "data: The server time is: {$time}\n\n";
flush();
?>
This works and the page gets updated every 5 seconds.
My question is: Why 5 seconds? Is this a default setting for SSEs or is it something to do with the php date functionality or some php.ini setting?
EDIT
I change the php to this:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
while(true)
{
$time = date('r');
echo "data: The server time is: {$time}\n\n";
flush();
sleep(1);
}
?>
and I get nothing, as if it is waiting for the php script to finish running (which it never will).
EDIT 2
PHP now changed to this (includes proper flush as suggested):
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
while(true)
{
$time = date('r');
echo "data: The server time is: {$time}\n\n";
while (ob_get_level() > 0)
ob_end_flush();
flush();
if (connection_aborted())
break;
sleep(1);
}
?>
Still doing nothing.
Related
Hi I'm currently working on a personal project which has two components. I want to POST "baby, 1" to my server, and when my server receives that "baby, 1", I want to change the webpage to reflect the date (currently using the date to test). I'm currently using Postman to test and largely borrowing code from W3Schools.
testpage.php
<html lang ="en">
<head>
<meta charset ="UTF-8">
<title>Title</title>
</head>
<body>
<div id = "result"></div>
<script>
if (typeof(EventSource) !== "undefined")
{
var source = new EventSource("server.php");
document.getElementById("result").innerHTML+="thug";
source.onmessage = function (event) {
document.getElementById("result").innerHTML += event.data + "<br>";
};
}else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
</script>
</body>
</html>
server.php
<?php
$bool = "";
if($_SERVER["REQUEST_METHOD"] == "POST") {
if (!empty($_POST["baby"])) {
$bool = $_POST["baby"];
if ($bool == 1) {
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$time = date('r');
echo "data: The server time is: {$time}\n\n";
flush();
}
}
}
?>
When I test with the w3schools default code
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$time = date('r');
echo "data: The server time is: {$time}\n\n";
flush();
?>
testpage.php updates properly. When I try to POST to server.php with (baby,1) testpage.php does not update. I am really struggling to figure out why this is happening.
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);
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
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.
Try to make a download page with pure php.
For those people that have javascript enabled, I plan to extend the download page with some feedback.
Have done some protyping...
when the user press on the download button (post) the download starts.
There is no page change and the java scripts are still executable on the download page.
Is this something that could rely on, that the javascript still executes after a forced download?
simple example, test.php:
<?php
if (!isset($_POST["submit"])) {
$content = '
<script type="text/javascript">
var count = 0;
function tick(){
count++;
console.log("tick() " + count);
setTimeout("tick()", 1000);
}
tick();
</script>
<form method="post" action="">
Download file</br>
<input type="submit" name="submit" value="Submit" />
</form>
';
echo $content;
} else {
$file = 'contentFile.zip';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename='.basename($file));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
}
?>