I have the following script:
function follow($file)
{
$currentSize = filesize($file);
$size = $currentSize;
$index=0;
while ($index<$currentSize) {
//echo "ENTERING LOOP!!!!";
clearstatcache();
$currentSize = filesize($file);
if ($size == $currentSize) {
usleep(100);
continue;
}
$fh = fopen($file, "r");
fseek($fh, $size);
while ($d = fgets($fh)) {
ob_end_flush();
echo $d;
ob_flush();
flush();
ob_start();
}
fclose($fh);
$size = $currentSize;
$index=$index+1;
}
}
follow("/var/www/devicemanagement/testFile.txt");
This script echoes a log file in real time and it works well when run in command line.
The following html code is meant to display the echoed lines from the php script:
<!DOCTYPE html>
<html>
<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.js"></script>
<script>
var sentData = {
'param1': 'value1',
'param2': 'value2'
};
function successCallback(returnedData) {
$('#myDiv').html(returnedData);
}
function doAjaxCall() {
$.get('/labtool/controllers/tailor.php', sentData, successCallback);
//$.get('testFile.php', sentData, successCallback);
}
$(document).ready(function () {
var id;
$('#doStuff').click(function () {
clearInterval(id);
//$.get('testFile.php', sentData, successCallback);
});
id = setInterval(doAjaxCall, 1000);
});
</script>
</head>
<body>
<div id="myDiv"><h2>Let AJAX change this text</h2></div>
<button type="button" id="doStuff">Change Content</button>
<div id="myDiv"></div>
</body>
</html>
I understand the key is using flush right, but despite my best efforts and a lot of experimenting I'm unable to get it to work.
Can anyone see what I'm doing wrong?
This works for me using info I gathered from probably many sources including stackoverflow, sorry about the formatting. Every time you have text to flush, simply call the function:
function flush_message($msg)
{
echo $msg;
// not a space, just '', I haven't tried removing it to see what happens
// cause I should really be working on something else right now!
echo str_pad('', 4096) . "\n";
ob_flush();
flush();
}
I also set
apache_setenv('no-gzip', 1);
ini_set('zlib.output_compression', 0);
at the beginning of script
Apparently there are lots of browser specific issues as well (regarding how big buffer until output is drawn) so you might want to test on different platforms to see how it performs.
Related
I'm working on a file that already has some code, and it uses php's ob_start() and ob_get_clean() functions around the jQuery being used. Is there a clear reason for why someone would do this?
ob_start();
?>
<script>
$(document).ready(function() {
$('div.scripture').on('click', function() {
$('div#schedule div.text').slideUp();
text = $(this).next('div.text');
if (text.is(":visible") == true) {
text.slideUp();
} else {
text.slideDown();
}
});
});
</script>
<?php
$additionalJS = (!empty($additionalJS)) ? $additionalJS : NULL;
$additionalJS .= ob_get_clean();
Unfortunately, This code isn't working because i wanna download files through php and need to hide the direct path of files uploaded in my server.
If i define complete path in variable.. example.com/files/filedownload.iso then it's working but it's pointless, because i wanna hide a path while downloading.
<form target="_blank" id="download_file" action="download.php" method="post">
<input name="ip" type="hidden" value="192.123.23.1">
<input name="filename" type="hidden" value="filedownload.iso"'; ?>
<div align="center">
<input alt="Submit" src="download.gif" type="image" />
</div>
</form>
The above code is POST method..
<?php
if(isset($_POST['ip']) && $_POST['ip']!="" && isset($_POST['filename']) && $_POST['filename']!=""){
$filename = $_POST['filename'];
}
$domain="http://example.com/".$filename;
//$redirect_url="http://example.com".$filename;
$redirect_url=$path;
$redirect_url= encrypt_download_link($domain,$path);
?>
<script type="text/javascript">
var max_time= 5; //Seconds
function Redirect()
{
window.location="<?php echo $redirect_url; ?>";
}
function refresh_remaining_time()
{
max_time = max_time-1;
if (max_time>=0) {
document.getElementById("waiting_time_span").innerHTML = max_time+" Seconds";
}
}
window.onload = function() {
setInterval(function () {
if (max_time>=0) {
refresh_remaining_time();
}
}, 1000); // Execute somethingElse() every 2 seconds.
setTimeout(function () {
Redirect();
}, 5000);
};
</script>
<?php
}
function encrypt_download_link($domain,$path){
$secret = '4rTyHHgtopSUm';
$expire = strtotime("+7 days");
$md5 = base64_encode(md5($secret.$path.$expire,true));
$md5 = strtr($md5, '+/', '-_');
$md5 = str_replace('=', '', $md5);
$url = $domain.$path."?st=".$md5."&e=".$expire;
return $url;
}
?>
I'm not sure if this would work for you, and it won't work for large files, but if you redirect users to a page with this code it will stream the file in binary down to their system. Don't be a hater if your files are larger and this won't work :)
P.S. I'd love to take credit for this, and I searched for the source (couldn't find it), but this hit my library at someone else's suggestion a few years back.
$nameFile = 'insert just name of file here'
$pathFile = 'insert file and path here';
$sizeFile = filesize($pathFile);
$pointerFile = fopen($pathFile, "rb"); // Open file for reading in binary mode
$contentFile = fread($pointerFile, $sizeFile);
fclose($pointerFile);
header("Content-length: ".$sizeFile);
header("Content-type: application/octet-stream");
header("Content-disposition: attachment; filename=".$nameFile.";" );
echo $contentFile;
I have problem with logging visit duration.
I wrote test html file like this:
<!DOCTYPE html>
<html>
<body>
<script language="JavaScript" type="text/javascript">
function enter() {
this.chrono = new Date().getMilliseconds();
alert("test");
}
function leave() {
this.chrono = new Date().getMilliseconds() - this.chrono;
var myAjax = new Ajax.Request('visitor_log/ajax_store_visit_duration.php?visit_duration=' + this.chrono.toString(),{
method: 'get',
onComplete:handlerFunction
});
return null;
}
window.onload = enter;
window.onbeforeunload = leave;
</script>
</body>
</html>
PHP file (visitor_log/ajax_store_visit_duration.php):
<?php
if(isset($_GET["visit_duration"]))
{
$text = $_GET["visit_duration"];
log($text);
}
else die("error");
function log($text)
{
$myFile = "test.txt";
$fh = fopen($myFile, 'wb');
fwrite($fh, $text);
fclose($fh);
}
?>
When I type in browser:
http://localhost/visitor_log/ajax_store_visit_duration.php?visit_duration=123
it creates text file as I want, but it seems that AJAX call in onbeforeunload event is not working.
Whats wrong with my code?
Edit:
I created test function to find problem with AJAX call.
function testajax(){
this.chrono = new Date().getMilliseconds() - this.chrono;
var blockingRequest = new XMLHttpRequest();
blockingRequest.open("GET", "visitor_log/ajax_store_visit_duration.php?visit_duration=" + 123, false); // async = false
blockingRequest.send();
return null;
}
window.onload = testajax;
</script>
</body>
This is not working too.
Ok, so purposefully NOT using jQuery:
here's the PHP:
<?php
function loggit($text) {
$myFile = "/tmp/test.txt";
$fh = fopen($myFile, 'wb');
fwrite($fh, $text);
fclose($fh);
}
if(isset($_GET["visit_duration"])) {
$text = $_GET["visit_duration"];
loggit($text);
}
else die("error");
?>
here's the HTML:
<!DOCTYPE html>
<html>
<body>
<script language="JavaScript" type="text/javascript">
function enter() {
this.chrono = new Date().getMilliseconds();
}
function leave() {
this.chrono = new Date().getMilliseconds() - this.chrono;
alert("test" + this.chrono);
var blockingRequest = new XMLHttpRequest();
blockingRequest.open("GET", "http://localhost/_TempFiles/temp.php?visit_duration=" + this.chrono.toString(), false); // async = false
blockingRequest.send();
return null;
}
window.onload = enter;
window.onbeforeunload = leave;
</script>
</body>
</html>
you want to use an async request (see the false sent to blockingrequest.open) - but beware this is a BLOCKING request (hence the name).
Also I changed the name of the php function from "log" to "loggit" log is the php natural logarithm function...
Could someone please save these 2 files and run them and tell me why I get the error " ob_flush() [ref.outcontrol]: failed to flush buffer. No buffer to flush". I tried googling around and it says that I have to use ob_start(); but when I do then it doesn't print out line by line, but rather returns the whole object from the FOR loop when it has completed. I'm kinda new to PHP so I'm not sure where else to look..
test_process.php
// This script will write numbers from 1 to 100 into file
// And sends continuously info to user
$fp = fopen( '/tmp/output.txt', 'w') or die('Failed to open');
set_time_limit( 120);
ignore_user_abort(true);
for( $i = 0; $i < 100; $i++){
echo "<script type=\"text/javascript\">parent.document.getElementById( 'foo').innerHTML += 'Line $i<br />';</script>";
echo str_repeat( ' ', 2048);
flush();
ob_flush();
sleep(1);
fwrite( $fp, "$i\n");
}
fclose( $fp);
main.html
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css" media="screen">
.msg{ background:#aaa;padding:.2em; border-bottom:1px #000 solid}
.new{ background-color:#3B9957;}
.error{ background-color:#992E36;}
</style>
</head>
<body>
<iframe id="loadarea" width="1024px" height="768px"></iframe><br />
<script>
function helper() {
document.getElementById('loadarea').src = 'test_process.php';
}
function kill() {
document.getElementById('loadarea').src = '';
}
</script>
<input type="button" onclick="helper()" value="Start">
<input type="button" onclick="kill()" value="Stop">
<div id="foo"></div>
</body>
</html>
You only need ob_flush() if an output buffer is active (for example by ob_start(), or by configuration settings). If you haven't, just remove the ob_flush(). Or you can make it conditional:
if (ob_get_level() > 0) {ob_flush();}
I think you are confusing ob_flush() with flush(). While ob_start() and ob_flush() handles a PHP internal output buffer that catches all outputs, flush() is the normal function that flushes STDOUT like in other programming languages.
Example:
<?php
ob_start();
echo "Foobar\nFoobar\nFoobar\n";
// Nothing printed yet
ob_flush(); // Now it is printed.
echo "Foobar\n"; // Printed directly, because contains a line ending.
echo "Foobar"; // Not printed, because normally buffers are flushed on line endings
flush(); // Printed.
EDIT:
Your output is not printed, because your webserver may buffer the contents. Try to turn off compression and output buffering:
#apache_setenv('no-gzip', 1);
#ini_set('zlib.output_compression', 0);
#ini_set('implicit_flush', 1);
Please also keep in mind, that Safari and Internet Explorer have an internal 1K buffer. So you need to add 1 KB of padding data (like spaces), to make them render.
EDIT 2:
Your implementation is broken. You want to poll your data with ajax. Use jQuery on the client side:
<div id="counter">0%</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js">
<script type="text/javascript">
function doPoll(){
$.post('script-that-returns-stuff.php', function(data) {
$("#counter").html(data);
setTimeout(doPoll,5000);
});
}
doPoll();
</script>
Then in script-that-returns-stuff.php:
<?php
$file = explode("\n", file_get_contents("/tmp/output.txt"));
$last_line = $file[count($file)-1];
echo $last_line."%";
Where is ob_start()?
ob_flush flushes the output buffer to your file handle. Maybe you have it wrong.
An example:
ob_start(); //start output buffering
echo 'hello world'; //not outputed
ob_flush(); //sends the output buffer so displays hello world.
manual
I'm using a standard php cache script on page.php
$cache = 'the_location/'.$id.'.html';
$expire = time() -3600 ;
if(file_exists($cache) && filemtime($cache) > $expire)
{
readfile($cache);
} else {
ob_start();
// some stuff
$pages = ob_get_contents();
ob_end_flush();
$fd = fopen("$cache", "w");
if ($fd) {
fwrite($fd,$pages);
fclose($fd);
}
echo $pages ; }
On main_page.php I'm loading page.php like so:
$('#div').load('page.php?id=' + id);
If I go straight to page.php?id=1234 the page is cached and file 1234.html appears in 'the_location'
Otherwise on main_page.php nothing happens ...
Help is much appreciated !
Edit : Everything works on main_page.php and page.php, page.php is correctly loaded into main_page.php but not cached, if I load page.php through browser it is cached.
I simulated this as basically as I could:
main_page.php:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head id="ctl00_Head1">
<script src="jquery-1.5.min.js"></script>
<script type="text/javascript">
var id = <?=$_GET['id']?>;
$(function(){
$('#div').load('page.php?id=' + id);
});
</script>
</head>
<body>
<div id="div">a</div>
</body>
</html>
page.php
<?php
$id = $_GET['id'];
$cache = 'the_location/'.$id.'.html';
$expire = time() -3600 ;
if(file_exists($cache) && filemtime($cache) > $expire)
{
readfile($cache);
} else {
ob_start();
echo 'This is a generated page';
$pages = ob_get_contents();
ob_end_clean();
$fd = fopen("$cache", "w");
if ($fd) {
fwrite($fd,$pages);
fclose($fd);
}
echo $pages;
}
This works for me. Things I noted while working through the code.
make sure you are setting id to php's $_GET['id'] in javascript in the main_page.php
make sure you are setting $id = $_GET['id']; on page.php
using ob_end_flush(); along with echo $pages is repetitive (content gets flushed, then shows up twice when the page is regenerated), use ob_end_clean() or $pages = ob_get_flush().
Have you looked at the request that is being sent using firebug? JQuery is probably appending a cache-busting GET variable to the URL hence busting your cache :D