Delay in populating session.upload_progress data - php

I'm trying to check the progress of files uploaded. I'm using the Kohana framework which has a Session class, but for the upload progress I'm using native PHP sessions. I'm calling session_start() in Kohana's bootstrap.php, which means session_start() will be called on every page request.
After the upload form is submitted, I wait 1 second and then begin calling a PHP file to check the upload progress using jQuery $.ajax().
The problem is that $_SESSION[$key] ($key contains the key for the upload data) isn't set on the first call to the PHP. I've tried debugging this quite a bit, and session_id() returns the correct session ID, so the session is definitely the right one and is active. I'm also waiting 1 second before checking the upload progress, so it's not a timing issue. I could fix this by continuing even if $_SESSION[$key] is not set, but the way to check if the upload is complete is when $_SESSION[$key] is unset.
The HTML form is created on-the-fly with jQuery because this is a multi-file upload. Here's the HTML for a generated form:
<form action="ajax/upload" id="form-HZbAcYFuj3" name="form-HZbAcYFuj3" method="post" enctype="multipart/form-data" target="frame-HZbAcYFuj3">
<iframe id="frame-HZbAcYFuj3" name="frame-HZbAcYFuj3"></iframe>
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="HZbAcYFuj3">
<input type="file" id="file-HZbAcYFuj3" name="photo" accept="image/jpeg,image/pjpeg,image/png,image/gif">
<button type="button">+ Select Photo</button>
</form>
Here's the PHP that the JavaScript calls to check the progress:
public function action_uploadprogress()
{
$id = isset($_POST['id']) ? $_POST['id'] : false;
if (!$id)
throw new Kohana_HTTP_Exception_404();
$progress = 0;
$upload_progress = false;
$key = ini_get("session.upload_progress.prefix") . $id;
if (isset($_SESSION[$key]))
$upload_progress = $_SESSION[$key];
else
exit('100');
$processed = $upload_progress['bytes_processed'];
$size = $upload_progress['content_length'];
if ($processed <= 0 || $size <= 0)
throw new Kohana_HTTP_Exception_404();
else
$progress = round(($processed / $size) * 100, 2);
echo $progress;
}
Here's the jQuery ajax() request:
this.send_request = function()
{
$.ajax(
{
url: 'ajax/uploadprogress',
type: 'post',
dataType: 'html',
data: { id: _this.id },
success:
function(data, textStatus, jqXHR)
{
if (textStatus == "success")
{
if (data < 100)
setTimeout(_this.send_request, 1000);
}
}
}
);
};

You are sending a POST called 'id' to the PHP script.
However, the documentation says that the upload progress will be available only when you send a POST with same name as session.upload_progress.name configured in php.ini.
So, in other words, if your session.upload_progress.name is set to default value (PHP_SESSION_UPLOAD_PROGRESS), you have to change the following line, in send_request function:
Change:
data: { id: _this.id }
To:
data: { PHP_SESSION_UPLOAD_PROGRESS: _this.id }
You also have to change the $_POST['id'] to $_POST['PHP_SESSION_UPLOAD_PROGRESS'] or $_POST[ini_get("session.upload_progress.name")] in the PHP script (and the name of input too in case it's not default).
The upload progress will be available in the $_SESSION superglobal when an upload is in progress, and when POSTing a variable of the same name as the session.upload_progress.name INI setting is set to. When PHP detects such POST requests, it will populate an array in the $_SESSION, where the index is a concatenated value of the session.upload_progress.prefix and session.upload_progress.name INI options. The key is typically retrieved by reading these INI settings, i.e.
Source: http://php.net/manual/pt_BR/session.upload-progress.php

Lets see if I can get some of that sweet sweet bounty.. My first thought is that the $key string is not getting set properly.
Try echoing its value out and doing a print_r on the entire $_SESSION variable to keep track of things.
Now I don't see a 'success' output from action_uploadprogress() at all. I see 100 which I guess indicates done but you aren't checking for that in js. I would recommend looking into that. Might as well echo out your calculations as well. I assume its very unlikely but make sure that you are uploading files properly and are able to determine their current size without any issue.
Another issue could be with how you are handling ajax with jquery. I'm not 100% sure about this but I think the success option has been depreciated (1.5+).
From : http://api.jquery.com/jQuery.ajax/
$.ajax({
type: "POST",
url: "some.php",
data: { name: "John", location: "Boston" }
}).done(function( msg ) {
alert( "Data Saved: " + msg );
});
The only way I've seen success being used is like this....
$.ajax({
type: "POST",
url: '/login/spam',
data: formData,
success: function (data) {
if (data == 'value') {
//Do stuff
}
}
});
However I could be completely wrong about this....your setup might be perfectly fine. What I want you to do is get is directly in the success/done function is
alert(data);
alert(textStatus); //if you still use it
This will tell you if you are getting a proper response from your ajax query.
I will check back a few times tonight and I'll be around tomorrow to help. Tell me if anything I said helps anything.

Related

Multiple Ajax call with same JSON data key calling one php file

I am trying to validate list of dynamic text fields.
Validation needs an AJAX call to interact with server.
At the backend I have written just one php file that reads the input request data and performs operation. Below is the example.
abc.js
row_count = 6
for (i = 1; i <=row_count; i++) {
id = "#val"+i.toString() ;
$(id).change(function(){
input_val="random";
$.ajax({
url:"url.php",
type:post,
async:true,
dataType: 'json',
data : {temp:input_val},
success:function(result){},
error: function (request, status, error) {}
});
});
}
url.php
<?php
$random_val = $_POST['temp'];
$cmd = 'systemcommand '.$random_val;
$flag = exec($cmd);
if ($flag == 0){
echo json_encode(array("status"=>'Fail'));
}
else{
echo json_encode(array("status"=>'Success'));
}
?>
It works fine when the row_count = 1 (Just one text field) but fails when the input is more than 1.
When the count is more than 1, the php script is not able to read the request data(The key in JSON data "temp"). it is blank in that case.
Any lead or help should be appreciated.
Thanks
Your javascript bit needs some adjusting, because you do not need to define an ajax for every single element. Use events based on a class. Also, since input behave differently than select, you should setup two different event class handlers.
function validateAjax ( element ) {
var input_val = element.val();// get the value of the element firing this off
$.ajax({
url: "url.php",
type: 'post',
async: true,
dataType: 'json',
data : { temp: input_val },
success: function(result) {
// check your result.status here
},
error: function (request, status, error) { }
});
}
$(".validate_change").on("change",function() { // for selects
validateAjax( $(this) );
});
$(".validate_input").on("input",function() { // for text inputs
validateAjax( $(this) );
});
And for your select or input you add that appropriate class.
<select class="validate_change" name="whatever"><options/></select>
<input class="validate_input" name="blah">
PS
I really worry about this code you have:
$cmd = 'systemcommand '.$random_val;
$flag = exec($cmd);
So, you are just executing anything that is coming in from a webpage POST var??? Please say this website will be under trusted high security access, and only people using it are trusted authenticated users :-)

Passing of javascript variable data to php variable in the same php file

I have a javascript that needs to pass data to a php variable. I already searched on how to implement this but I cant make it work properly. Here is what I've done:
Javascript:
$(document).ready(function() {
$(".filter").click(function() {
var val = $(this).attr('data-rel');
//check value
alert($(this).attr('data-rel'));
$.ajax({
type: "POST",
url: 'signage.php',
data: "subDir=" + val,
success: function(data)
{
alert("success!");
}
});
});
});
Then on my php tag:
<?php
if(isset($_GET['subDir']))
{
$subDir = $_GET['subDir'];
echo($subDir);
}
else
{
echo('fail');
}?>
I always get the fail text so there must be something wrong. I just started on php and jquery, I dont know what is wrong. Please I need your help. By the way, they are on the same file which is signage.php .Thanks in advance!
When you answer to a POST call that way, you need three things - read the data from _POST, put it there properly, and answer in JSON.
$.ajax({
type: "POST",
url: 'signage.php',
data: {
subDir: val,
}
success: function(answer)
{
alert("server said: " + answer.data);
}
});
or also:
$.post(
'signage.php',
{
subDir: val
},
function(answer){
alert("server said: " + answer.data);
}
}
Then in the response:
<?php
if (array_key_exists('subDir', $_POST)) {
$subDir = $_POST['subDir'];
$answer = array(
'data' => "You said, '{$subDir}'",
);
header("Content-Type: application/json;charset=utf-8");
print json_encode($answer);
exit();
}
Note that in the response, you have to set the Content-Type and you must send valid JSON, which normally means you have to exit immediately after sending the JSON packet in order to be sure not to send anything else. Also, the response must come as soon as possible and must not contain anything else before (not even some invisible BOM character before the
Note also that using isset is risky, because you cannot send some values that are equivalent to unset (for example the boolean false, or an empty string). If you want to check that _POST actually contains a subDir key, then use explicitly array_key_exists (for the same reason in Javascript you will sometimes use hasOwnProperty).
Finally, since you use a single file, you must consider that when opening the file the first time, _POST will be empty, so you will start with "fail" displayed! You had already begun remediating this by using _POST:
_POST means that this is an AJAX call
_GET means that this is the normal opening of signage.php
So you would do something like:
<?php // NO HTML BEFORE THIS POINT. NO OUTPUT AT ALL, ACTUALLY,
// OR $.post() WILL FAIL.
if (!empty($_POST)) {
// AJAX call. Do whatever you want, but the script must not
// get out of this if() alive.
exit(); // Ensure it doesn't.
}
// Normal _GET opening of the page (i.e. we display HTML here).
A surer way to check is verifying the XHR status of the request with an ancillary function such as:
/**
* isXHR. Answers the question, "Was I called through AJAX?".
* #return boolean
*/
function isXHR() {
$key = 'HTTP_X_REQUESTED_WITH';
return array_key_exists($key, $_SERVER)
&& ('xmlhttprequest'
== strtolower($_SERVER[$key])
)
;
}
Now you would have:
if (isXHR()) {
// Now you can use both $.post() or $.get()
exit();
}
and actually you could offload your AJAX code into another file:
if (isXHR()) {
include('signage-ajax.php');
exit();
}
You are send data using POST method and getting is using GET
<?php
if(isset($_POST['subDir']))
{
$subDir = $_POST['subDir'];
echo($subDir);
}
else
{
echo('fail');
}?>
You have used method POST in ajax so you must change to POST in php as well.
<?php
if(isset($_POST['subDir']))
{
$subDir = $_POST['subDir'];
echo($subDir);
}
else
{
echo('fail');
}?>
Edit your javascript code change POST to GET in ajax type
$(document).ready(function() {
$(".filter").click(function() {
var val = $(this).attr('data-rel');
//check value
alert($(this).attr('data-rel'));
$.ajax({
type: "GET",
url: 'signage.php',
data: "subDir=" + val,
success: function(data)
{
alert("success!");
}
});
});
});
when you use $_GET you have to set you data value in your url, I mean
$.ajax({
type: "POST",
url: 'signage.php?subDir=' + val,
data: "subDir=" + val,
success: function(data)
{
alert("success!");
}
});
or change your server side code from $_GET to $_POST

Call a php function in MVC using AJAX?

I am currently migrating an already built web application to MVC, and I'm figuring out that I'm too newbie to do some kind of changes. There are some ajax calls that are freaking me out. I'll try to be as clear as possible, but due to my inexperience I'm not sure if I won't let some important information by the way.
The point is in the old application, things go this way:
In the php code:
if ($action_user == 'show_alerts') {
$list = array();
$query = "SELECT alert_type FROM alert_contact WHERE NOT
deleted AND user_email=" . typeFormat($email);
$result = mysqli_query($db, $query) or die('Error in query "'.$query . '": ' . mysqli_error($db));
while ($db_field = mysqli_fetch_assoc($result)) {
$list[] = $db_field['alert_type'];
}
echo json_encode($list);
In the jquery code:
$.ajax({
type: 'POST',
url: 'userpost.php',
data: $('#userForm').serialize(),
cache: false,
dataType: 'json'
Here comes my problem, and since I don't have an userpost.php file anymore, I have to send it to the index.php and call my users component by a get petition, which I don't like, but I coudn't find another way to do it. And, what is even worse, I don't know at all how ajax is getting the variables that it needs. It must be a pretty basic mistake, but I recognize my skills at this point are't so good. That's what I'm doing in my version:
In the php code:
if ($action_user == 'show_alerts') {
$list = ModelUser::getAlertContact($act_email);
echo json_encode($list);//I predict that ajax don't reach this line, but not sure
}
In the jquery code:
$.ajax({
type: 'POST',
url: 'index.php?option=users',
data: $('#userForm').serialize(),
cache: false,
dataType: 'json',
success: function(data) {
alert ('gotcha');
$.each(alertsarray, function(index, value) {
if ($.inArray(value, data) === -1) {
$("#sub" + value).prop("checked", false);
$('#alert' + value).removeClass("list_alert_sub");
}
else {
$("#sub" + value).prop("checked", true);
$('#alert' + value).addClass("list_alert_sub");
}
});
},
error: function(data) {
alert("¡Error (ajax)!");
}
});
Any help would be appreciated, and if there's some more information I've missed, please let me know. Thanks in advance.
UPDATE:
I've been making some progress but don't seem to find a real solution. Now I know that the url has to be the controller, so I'm using 'components/userpost/controller.php' as it, and it reaches the ajax call, cause the success alert is showing up. The problem is the MVC way, because I send ajax to the controller, but since I don't have a reload in the page, all the includes are failing so they are obviously not being loaded, and I'm getting errors like this:
PHP Warning: include(components/userpost/model.php): failed to open
stream: No such file or directory in
/var/www/html/viewer_mvc/components/userpost/controller.php on line 3,
referer: http://localhost/viewer_mvc/index.php
Really hope you guys can show me where am I failing, and if there's a special way to do these thing in MVC.
For the JQuery call it makes a POST request to index.php?option=users with JSON data. The form with the ID userForm is serialized using the Jquery serialize method.
The .serialize() method creates a text string in standard URL-encoded notation. It can act on a jQuery object that has selected individual form controls
$.ajax({
type: 'POST',
url: 'index.php?option=users',
data: $('#userForm').serialize(),
cache: false,
dataType: 'json'
Now for your PHP sample
if ($action_user == 'show_alerts') {
$list = ModelUser::getAlertContact($act_email);
echo json_encode($list);//I predict that ajax don't reach this line, but not sure
}
This code will be looking for variables that probably don't exist anymore if it is a different file i.e. is there an $action_user variable?
To start reimplementing it you will need to add the logic so that it checks the POST variable if your not using the framework code. So if you have a form element with the name 'name' then that will be available in your PHP script POST variable
$_POST['name']
[How to call a PHP function in MVC using AJAX]
$.ajax({
type: 'POST',
url: 'save-user.php',
data: { fname: "manish", email: "manishkp#com", role:"admin"},
success: function(data) {
console.log(data);
if(data == 'error')
{
$('#Register_error').text('Must Be filled...');
$('#Register_error').show();
}
else {
$('#Register_error').hide();
$('#Register_success').text('Successfully submit');
$('#Register_success').show();
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<?php
$fname = $_POST['fname'];
$email = $_POST['email'];
$role = $_POST['role'];
if(!empty($fname) && !empty($email) && !empty($role))
{
#MYSQL CONNECTION QUERY #
echo"success";
}
else{
echo "error";
}
?>

Ajax request for PHP loop number

I'm currently trying to get a PHP loop status and update a HTML5 progress bar.
The loop is triggered by a button click and set to 5000 with 1sec sleep() after every execution. I of course also made an Ajax request to which reuqests the current loop number every second and update the progress bar. However the request always waits until the loop is completed and shows me a number like "1234567891011..."
This is my JQuery code which is very simple because it's only for testing and learning purpose
function getStatus() {
$.ajax({
url : 'ajax.php',
dataType: "html",
type: "POST",
data: {request: 'request',},
success: function( data ) {
//Call function to update status on the loading bar
updateBar(data);
}
});
//Update loading bar
function updateBar(data) {
$('progress').attr('value', data);
}
}
function setGo() {
$.ajax({
url : 'ajax.php',
dataType: "html",
type: "POST",
//async: false,
data: {status: 'GO',},
success: function( data ) {}
});
}
$('#start').click(function(event) {
setGo();
setInterval(function() {
getStatus();
}, 1000);
});
This is my php Code
<?php
//Overwrite php execution limit
set_time_limit(120);
if($_POST['status'] = 'GO') {
$number = 5000;
$counter = 0;
for($i=0; $i != $number; $i++) {
$counter++;
sleep(1);
if(isset($_POST['request'])) {
echo $counter;
}
}
}
?>
I tried a lot of different ways and read a lot of posts but somehow nothing worked for me.
Hope someone got an idea.
Take a good look at your "echo $counter;" part in your PHP script, that's in a (5000 times) loop.
After the PHP code is interpreted and executed, the web server sends resulting output to its client, usually in form of a part of the generated web page – for example, PHP code can generate a web page's HTML code
From PHP's wiki page
This basically means that the whole php file will always be executed before returning the output. The loop will be executed 5000 times before returning the output.

Ajax success if statement and echo mySQL query result

I have an Ajax script that makes a call to a php file on my server every twenty seconds.
The server then runs a simple mysql query to return the contents of a particular field.
If that field is blank I want the php file to echo the word "pending", which when caught by the success handler will recall the initial function. However if that field is not blank, it will contain a URL to which I want to redirect the user to. That field will update any where between 5 seconds and 5 minutes from the start of the first call and that time cannot be changed.
I think the main issue may be with my php file, in that I dont think it is echoing the data in a way that the success handler recognises. However I have detailed both parts of my code as whilst the success handler seems to be constructed correctly I am not 100% sure.
Very new to this, so apologies if I have not explained myself correctly but if anyone could assist that would be great:
UPDATE - for clarity what I am looking to achieve is as follows:
Ajax call to my php file.
PHP file queries database
If field queried contains no data echo the word "pending" to the ajax success handler (IF) which in turn recalls the original function / ajax call.
If field queried contains data (will be a URL) echo this result to the ajax success handler (ELSE)in a format that will redirect the user via window.location.assign(data).
FURTHER UPDATE
I managed to solve this question with using a combination of the advice from #mamdouhalramadan and #martijn
I also have changed setInterval to setTimeout as the poll function was causing responses to stack up should the server be running slowly and as such cause errors. I also added in cache: false and a further option in the success handler to take into account slightly different behaviour in IE:
AJAX
function poll() {
$.ajax({
url: 'processthree.php?lead_id='+lead_id,
type: "GET",
cache: false,
async: false,
success: function(data3) {
//alert("pending called " + data3)
if(data3.indexOf("pending") >-1 ){
setTimeout(poll, 20000);
}
else if ( (navigator.userAgent.indexOf('MSIE') != -1) ) {
//alert("Submit success - MSIE: " + data3);
parent.window.location.replace(data3);
}
else{
//alert("process three called " + data3)
window.top.location.assign(data3);
}
},
error: function(xhr, error){
//alert("Error");
//alert("Error: " + error + ", XHR status: " + xhr.status);
},
});
}
setTimeout(poll, 20000);
PHP
$query = ("SELECT column FROM table WHERE id = '$lead_id'") or die(mysql_error());
$result = mysql_query($query);
$return = array();
while($row = mysql_fetch_assoc($result))
{
$return = 'pending';
if($row['column'] != '')
{
$return = $row['column'];
}
}
echo $return;
I believe using json might help you out here, not to mention it is safer, like so:
function poll() {
$.ajax({
url: 'processthree.php?lead_id='+lead_id,
type: "GET",
dataType: 'json',//specify data type
success: function(data3) {
if(data3.res.indexOf("pending") >-1 ){
//rest of the code.....
then in your php:
$return = array();
while($row = mysql_fetch_assoc($result))
{
$return['res'] = 'pending';
if($row['column'] != '')
{
$return['res'] = $row['column'];
}
}
echo json_encode($return);
Note: use PDO or MYSQLI instead of mysql as it is deprecated.

Categories