PHP + jQuery Synchronization problem - php

I'm using jQuery + PHP on my website and I want to do something like this:
To simplify things I've got a page with 2 buttons () and according to which I click I want to start a script in background (php script) so I do a simple thing with jquery:
$("#button1").click(function(){
$.post("script.php", {val:"but1"}, function(result){
alert(result); // I want something with the result
});
});
$("#button2").click(function(){
$.post("script.php", {val:"but2"}, function(result){
alert(result);
});
});
and in the script.php I've got a simple if statement deciding what I should do.
In the php script I'm downloading a file and I want to create a progress bar of the file download. The php script would return me values (echo percentage; flush();) in some time interval.
And here comes the problem - when I echo those percentage values and flush it refreshes it "just in php" but the jquery waits until the script is finished anyway. Is there a way to get those values as they appear (after flush) or is there a completely other approach to this? I can't think of anything else right now, maybe I shouldn't be using jquery at all.
Thanks for the help.

You can store the progress in a text file or DB while running the script and then have another file get the result via AJAX calls.
JS/HTML
<script>
$(function() {
var id;
var timeoutLength = 1000;
$("#button1").click(function() {
$("#result").html("");
// Create unique identifier
id = (new Date().getTime()) + "-" + Math.floor(Math.random()*100);
$.get("script.php", {id: id}, function(result){
$("#result").html(result);
});
setTimeout(checkProgress, timeoutLength);
});
function checkProgress() {
$.get("script.php", {progress: true, id: id}, function(data) {
prog = parseInt(data);
// Display progress bar
if(prog < 100) {
$("#progress").css({ display: 'block', width: prog });
$("#progress").html(prog + "%");
setTimeout(checkProgress, timeoutLength);
} else {
$("#progress").css('display', 'none');
}
});
}
})
</script>
<button id="button1">Click</button>
<div id="progress" style="background: green"></div>
<div id="result"></div>
script.php
<?php
function getProgress($file) {
return (file_exists($file)) ? file_get_contents($file) : 0;
}
function setProgress($file, $progress) {
file_put_contents($file, $progress);
}
// Remove invalid characters
$id = str_replace('/[^a-zA-Z0-9\-_]/', '', $_GET['id']);
$file = "progress-" . $id . ".txt";
if(isset($_GET['progress'])) {
echo getProgress($file);
} else {
// Do something and update progress
for($i = 10; $i <= 100; $i += 10) {
// Do something
setProgress($file, $i);
sleep(1);
}
unlink($file);
echo "Result: " . rand(1, 100);
}
Edit:
Added support for multiple requests and simple progress bar.

i believe that what all you need is the pecl uploadprogress package
it is not very easy to install and its not sure it works, i have find hard to make it work under certain server configurations, but i think its a good shot
EDIT: sorry i didnt see you mention download so have a look here

Below script will work for the progress-bar.
But, what I would do is, trigger an AJAX call to start the download and trigger another AJAX call to start receiving the input (using How to show file download progress in PHP Shell Scripting?).
PHP:
<?php
echo "wget '$feedURL'\n";
$execute = "wget -O ".$filePath." '$feedURL'\n";
$systemOutput = shell_exec($execute);
$systemOutput = str_replace( "\n", "\n\t", $systemOutput);
echo "\t$systemOutput\n";
?>
GetProgress:
function getProgress(){
GDownloadUrl("getprogress.php?progress_key=<?php echo($unique_id)?>",
function(percent, responseCode) {
document.getElementById("progressinner").style.width = percent+"%";
if (percent < 100){
setTimeout("getProgress()", 100);
}
});
}
Here is nice implementation with the help PHP's APC to get a nice progress-bar during UPLOAD of a file - http://www.haughin.com/2007/10/23/php-upload-progress-with-php-52-apc/

Alternative solution:
You can store the progress of downloading file into $_SESSION array inside PHP.
Besides that, you can write a dedicated PHP to only retrieve this percentage from session. This PHP will be called from your client's AJAX. This way the proccess won't take so much resources from server to calculate or to echo the download's percentage.
Try to avoid I/O from files if you are going to handle high rates of reading/writing onto them. Session variables are less expensive to achieve this functionality.

Provided that your PHP has some way to know the progress percentage, you should do multiple requests for progress updates:
function receiveProgress(data) {
// update progres indicator here
if (parseFloat(data) < 100) {
setTimeout(checkProgress, 100);
} else {
pressedButton = '';
}
}
function checkProgress() {
$.post("script.php", {val:pressedButton}, receiveProgress);
}
var pressedButton = '';
$("#button1").click(function(){
pressedButton = 'but1';
checkProgress();
});
This will ask server for progress updates every 100ms

Related

using ajax to fetch a result from php and reload page

So I have been working on this for hours now, I have read a bunch of StackOverflow posts and I am still having no luck.
I have a page that has 2 sections to it, depending on the int in the database will depend on which section is being displayed at which time.
My goal is to have the page look to see if the database status has changed from the current one and if it has then refresh the page, if not then do nothing but re-run every 10 seconds.
I run PHP at the top of my page that gets the int from the database
$online_status = Online_status::find_by_id(1);
I then use HTML to load the status into something that jquery can access
<input type="hidden" id="statusID" value="<?php echo $online_status->status; ?>">
<span id="result"></span>
So at the bottom of my page, I added some jquery and ajax
$(document).ready(function(){
$(function liveCheck(){
var search = $('#statusID').val();
$.ajax({
url:'check_live.php',
data:{search:search},
type:'POST',
success:function(data){
if(!data.error){
$newResult = $('#result').html(data);
window.setInterval(function(){
liveCheck();
}, 10000);
}
}
});
});
liveCheck();
});
this then goes to another PHP page that runs the following code
if(isset($_POST['search'])){
$current_status = $_POST['search'];
$online_status = Online_status::find_by_id(1);
if($current_status != $online_status->status){
echo "<script>location.reload()&semi;</script>";
}else{
}
}
the jquery then loads into the HTML section with the id of "result" as shown earlier. I know this is a very bad way to do this, and as a result, it will work at the beginning but the longer you leave it on the page the slower the page gets, till it just freezes.
If anyone is able to point me towards a proper method I would be very grateful.
Thank you!!
js:
(function(){
function liveCheck(){
var search = $('#statusID').val();
$.ajax({
url:'check_live.php',
data:{search:search},
type:'POST',
success:function(data){
if(data.trim() == ''){
location.reload();
}else{
$('#result').html(data);
window.setTimeout(function(){
liveCheck();
}, 10000);
}
}
});
}
$(function(){
liveCheck();
});
})(jQuery)
php:
<?php
if(isset($_POST['search'])){
$current_status = $_POST['search'];
$online_status = Online_status::find_by_id(1);
if($current_status != $online_status->status){
$data = '';
}else{
$data = 'some html';
}
echo $data;
}
Your page is slowing down because you are creating a new interval every time you call the liveCheck function. Over time, you have many intervals running and sending requests to your PHP file concurrently. You can verify this behavior by opening the developer console in your browser and monitoring the Network tab.
What you should do instead is set the interval once, and perform the $.ajax call inside that interval. Additionally, it's good practice to not send a new request if a current request is pending, by implementing a boolean state variable that is true while an request is pending and false when that request completes.
It looks like the intended behavior of your function is to just reload the page when the $online_status->status changes, is that correct? If so, change your PHP to just echo true or 1 (anything really) and rewrite your JS as:
function liveCheck() {
if (liveCheckPending == true)
return;
liveCheckPending = true;
var search = $('#statusID').val();
$.ajax({
url:'check_live.php',
data:{search:search},
type:'POST'
}).done(function(data){
if (!data.error)
location.reload();
}).always(function(data){
liveCheckPending = false;
});
}
var liveCheckPending = false;
setInterval(liveCheck, 10000);

PHP and AJAX: Echo during process

little issue over here.
I have a php function that is called via AJAX and looks like this:
function processActiveDirectory(){
$var = new GetLDAPUsers;
echo "Getting Users from Active Directory.... <br />";
$adusers = $var->getAllUsers();
echo "setting up images.... <br />";
// processing more stuff
echo "finished";
}
I'm trying to get a "live- log" echo. Meaning before every step the echo should output to a Log area, one step after another. So the user knows what's going on.
But the Problem is, that the log doesn't appear during the process, it just fills in at the whole text at the end of the process. Everything else works fine. The Log just doesn't appear at runtime, but after the function is finished it appears at the right position.
My AJAX call:
jQuery(document).ready(function($) {
$('#lii-form').submit(function() {
data = {
action: 'lii_map_images'
};
$.post(ajaxurl, data, function(response){
$('#lii_log').html(response);
});
return false;
});
});
This is how it's build:
Edit
Other than in this thread I'm already using an ajax call, to call the function. It's within the called function that I'm echoing stuff...
Edit 2
I'm using wordpress
Sorry I can't offer more informations, because of enterprise restrictments.
This is a short over-view on your need. Please develop further with this idea.
This uses two AJAX calling - one for the main process and other for progress:
Script:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript">
//Start the main process
$.ajax({
url: 'main.php',
success: function(data) {
}
});
function getProgress(){
$.ajax({
url: 'progress.php',
success: function(data) {
$("#progress").html(data);
if(data != "finished"){
getProgress();
}
}
});
}
//Start the progress section
getProgress();
</script>
<div id="progress"></div>
main.php
<?php
$arr = ['Getting Users from Active Directory....','setting up images....','finished'];
foreach($arr as $value) {
session_start();
$_SESSION["progress"]=$value;
session_write_close();
sleep(1);
}
progress.php
<?php
session_start();
sleep(1);
echo $_SESSION["progress"];
So your processActiveDirectory will come under Main.php and echo should be replaced with SESSION variable
I think there is no need in such thing as LOG process WITH AJAX. AJAX is too heavy thing and it could be a bad design if you want it. It's better to use web sockets or not use at all

Phantomjs not creating screenshot

I was try to create a web screenshot with phantomjs,But alwaise it result a blank image.I am using Fedora OS.Here is my javascript.
screen.js
var WebPage = require('webpage');
page = WebPage.create();
page.open('http://google.com');
page.onLoadFinished = function() {
page.render('googleScreenShot' + '.png');
phantom.exit();}
And here is my php code
shot.php
$exec = '/var/www/html/test/bin/phantomjs /var/www/html/test/screen.js';
$escaped_command = escapeshellcmd($exec);
exec($escaped_command);
But the created image was blank.phantomjs have executre permission.Please help me
I am not sure but this may work,try it
var WebPage = require('webpage');
page = WebPage.create();
page.open('http://google.com');
page.onLoadFinished = function() {
window.setTimeout(function () {
page.render('googleScreenShot' + '.png');
phantom.exit();
}, 2000);
}
You have a problem because the time your code execute the next line of code is more faster than phantomjs logging that page.onLoadStarted is True.
easy and clean way to fix this is by adding a time interval of 100 ms between each function and make all your code in functions, check Vijay Boyapati method for more clarification : https://stackoverflow.com/a/9256079/1738230
In dealing with this problem I completed a code module, as follows:
link
You can download it locally, and then invoke it by command
phantomjs rasterize.js "http://www.google.com" 800px*800px > wait.html

$.get function not running in Chrome but working in IE and FireFox

I'm working on a site that uses php POST to upload files to a server and i'm trying to add a progress bar to the uploads.
I followed this guide:
http://www.ultramegatech.com/2010/10/create-an-upload-progress-bar-with-php-and-jquery/
It works great in ie and firefox. But the progressbar never updates in chrome.
This function gets called with a timeout of "500".
function updateProgress(id) {
var time = new Date().getTime();
// Make a GET request to the server
// Pass our upload identifier as a parameter
// Also pass current time to prevent caching
$.get('progressbar.php', { uid: id, t: time }, function (data) {
// Get the output as an integer
var progress = parseInt(data, 10);
if (progress < 100 || !started) {
var div = document.getElementById('statusfield');
div.innerHTML = progress + '%';
// Determine if upload has started
started = progress < 100;
// If we aren't done or started, update again
updateProgress(id);
}
if (progress > 99) {
var div = document.getElementById('statusfield');
div.innerHTML = 'Komprimerar fil...';
}
// Update the progress bar percentage
// But only if we have started
started && pbar.progressbar('value', progress);
});
}
This function calls the .php file "progressbar.php" which passes the upload progress back as a percentage number.
progressbar.php:
<?php
if (isset($_GET['uid'])) {
// Fetch the upload progress data
$status = uploadprogress_get_info($_GET['uid']);
if ($status) {
// Calculate the current percentage
echo round($status['bytes_uploaded']/$status['bytes_total']*100);
}
else {
// If there is no data, assume it's done
echo 100;
}
}
?>
I have tested the code in chrome and the function "updateProgress" gets called. But it never gets past the:
$.get('progressbar.php', { uid: id, t: time }, function
Does anyone have any clue on what could be wrong?
Thanks!
In chrome go to dev tools (Options -> Tools -> Developer tools) and look at the network panel. Once the $.get method is called you will see your request and the result - you can see if it fails (for example if a 404 happens) so maybe chrome doesn't set the address as it should or if the sent data / return data isn't ok.

Reload contents from the log file on the page using AJAX

I am running a shell script in the background and redirecting the output to a log file in php. I want to display the contents from the log file on the page. I am able to do that using the code below.
<?php
$logfile = "hello";
?>
function displayOutput()
{
var html = <?php
echo filesize($logfile)
? json_encode(file_get_contents($logfile))
: '"Log file is getting generated"';
?>;
document.form.text1.value = html;
}
However, the log file keeps updating till the script completes executing. How can i reload the updated contents from the file on the same page?
The technique that I developed + discuss here may be useful:
https://web.archive.org/web/20150206001444/http://commavee.com/2007/04/13/ajax-logfile-tailer-viewer/
It's been around for a while + works well.
You need to set an interval timer to call your function every n seconds. Have a look at this answer to help you out - how to schedule ajax calls every N seconds?.
setInterval(displayOutput, (10 * 1000));
// reload log contents every 10 seconds
Maybe what you want basic XMLHttpRequest usage.
I am not really php guy, neiter javascript guru, just trying to give you an idea
function refreshText()
{
if (window.XMLHttpRequest)
{
xhttp = new XMLHttpRequest();
}
else // for IE 5/6, just in case
{
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xhttp.open("GET","/page.php?action=download_log_file", false);
xhttp.send();
document.form.text1.value = xhttp.responseXML;
}
setInterval(refreshText, (10 * 1000)); // refresh text1.value every 10 seconds
same thing using jQuery
setInterval(function {
$.get('/page.php?action=download_log_file', function(data) {
$('#text1').val(data);
});
}, (10 * 1000));
The handler script at the server just prints file data, see
http://www.w3schools.com/xml/xml_server.asp for example
I've implemented "COMET-like" functionality recently to do just this. The way it works is to have an AJAX poll with a long timeout:
var lines = 0
function getLog(file, lines) {
$.ajax({
type: 'POST',
url: 'http://thissite.com/getLogFile.php?File=' + file + '&Lines=' + lines,
dataType: 'json',
timeout: 400000,
error:
function() {
return false;
},
success:
function(data) {
if (data.Error) {
alert(data.Message)
} else {
if (data.Lines > lines) {
// do something with data.LogLines, e.g. add to a textarea
}
getLogFile(file, data.Lines)
}
}
})
}
The back end script then simply loops like this:
Count the number of lines in the log file
If it's the same as lines, sleep (say for a second), then go back to 1
If the number of lines is greater, return the new lines, and the new line count, and exit
After some number of iterations (I use 100), exit and return the existing line count
The data structure returned by the back end script is JSON:
{
Error: // 0 or 1,
Lines: // Number of lines
Text: // New lines from log file
}
This works just like 'tail -f' in UNIX, but in a browser!

Categories