I am calling one jquery ajax request in my PHP code. This code fetch the data from database and export into the excel file. Once ajax request will success, i will get excel file popup download box. This feature is working fine in all browser.
Now, problem is when that jquery request is taking more time (7-8 minutes), excel file is created on the server, but download box is not popup and after 30 minutes i am getting timeout error.
what could be the problem, file is created on the server in 7 minutes but i am not getting any response from ajax request. I am also checked the timeout for ajax request it is set for 30 minutes.
Even if you manage to solve the timeout, making your clients wait 7 to 8 minutes without any progress feedback will be far from ideal. Better way would be to initiate the export on the server and return immediately. Once this returns you can give a progress message that says 'Export in progress..' or something. Then you can have an AJAX call that periodically checks the status of the export and returns the appropriate status message. Once exporting is done, you can change the progress feedback to 'Export complete: Download file' with Download file being a link to the excel file created on the server. you can also trigger a click on that link via code to automatically start the download.
i.e.
Assuming you have a DIV with class status which shows the export status
First AJAX call to initiate the export:
$.post({
url: '/export/',
...
success: function(data) {
$('.status').html('Export in progress. Please wait...');
}
});
Second AJAX call to poll export progress
$.post({
url: '/exportstatus/',
...
success: function(data) {
if(data=='OK') {
$('.status').html('Export complete: <a class="exportedfile" href="/path/to/exported/file">Download File</a>');
setTimeout(function() {
$('.status').find('a').click(); // trigger autostart of download
}, 1000);
}
}
});
You're doing it wrong: you don't want to force a user to be stuck on a page for more than a few seconds at most in order to get service from your app.
Instead, use a widget that will periodically query a status page (with ajax, of course) and display a message when the job is done.
(What kind of excel file is taking 7 minutes to generate? A db dump?)
Edit:
Different browsers will behave differently with long ajax requests, so don't depend on them waiting around forever even if the user is willing to. Your app will be much more robust if you decouple requesting a report generation and downloading the report.
This should give you an idea of what I'm talking about:
create_my_excel_file.php:
$_SESSION['excel_status']='generating';
create_the_excel_file();
$_SESSION['excel_status']='finished';
check_status.php:
echo $_SESSION['excel_status'];
user_interface.php:
<script type="text/javascript">
function initiateRequest(){
$.ajax('create_my_excel_file.php');
setInterval('checkForCompletion()', 5000);
}
function checkForCompletion(){
$.get('check_status.php', function(data){
if('finished'==data){
alert('Completed! Download the file now.');
location.href='file_download.php';
}
});
}
</script>
Generate the file
Related
So, I'm sending a form with ajaxForm which will send data, open spinner.gif, then on success close spinner and reload the page:
$('#form').ajaxForm({
beforeSubmit:function(){
spinnerLoad();},
success: function(data){
spinnerDone();
window.location.href ="sample.php";
}
});
Then the form is handled like this:
if (isset($_POST['save'])){
exec("/directory/script.php $args");
}
So this page, 'script.php' executes another script on DB, so it may take a long time. When there is not many data, it works fine, but whenever I have much, after a time 'script.php' wents 404, and the spinner.gif never stops.
I need to find a way to extend timeout somehow (ajax timeout option seems not suitable) or another way.
Sending the script.php page or the DB script to background is not ok - it must be finished in order to continue working.
I'll be glad to any comments/directions to look.
I have to export large file in excel format and download it. i am using php excel. File is very large so it is taking much time in export. so i am using async ajax call and on server side, i am using session_write_close. Through this i can send concurrent calls.this is working fine if i stay on the same page...
but when i send ajax call to export and download file and after that i redirect to a new page before the completion of that ajax call then that ajax call got cancelled and unable to download file. how can i export a file and then download it even after user has been redirected to a new URL.
There are several ways to perform download action on same page. Use of async may cause issues, your application may feel lagging between ajax operation.
As per my opinion you can do your ajax request in this way.
Upon creation of file use command-line approach if its possible. Or you can simply use system command with curl or elinks command and pass the url which is being used to generate the excel file.
curl http://mysite/generate/excel?id=123
or
elinks http://mysite/generate/excel?id=123
By using ajax ( sync ) you can make a request with keep alive option and check inside your code if file is created with some interval. your code will be like this
while (!file_exists("path/to/excel_file.xlsx")) {
usleep(2000);
}
echo json_encode(["status" => true, "file_url" => "http://mysite/url/to/excel_file.xlsx"]);
Once you get response from ajax, On success function call below function with file url to download file through iframe on the same page.
downloadAttachment(response.file_url)
/* Amazing download management with error handling */
var downloadAttachment = function(link){
var iframe = document.createElement("iframe"), iframeWindow;
iframe.src = link;
document.body.appendChild(iframe);
iframe.onload = function(){
response = JSON.parse($(iframe).contents().text())
if(!response.status)
{
alert(response.message);
$(iframe).remove();
}
}
setTimeout(function(){
$(iframe).remove();
},10000)
}
This is logical flow of how to download big files if it is taking long time to generate.
I have a series of buttons on a page that when a user clicks on them they trigger a PHP script via jQuery .ajax(). Currently, I append a concatenated string dump of "progress updates" to a status placeholder DIV via the success: function(data) { $('#divplaceholder').append(data); ...} parameter. My problem is I would like to print real-time progress updates to that placeholder DIV as the execution "echoes" them.
I have read many SSE examples, tutorials, done extensive googling and I think I have an idea on how to send the "messages" back from the server but I have been unable to find an example on how to actually trigger tasker.php via jQuery to send the updates back when the user actually pushes the button. Currently my .ajax() call is being triggered by a jQuery .on('click') event.
I'm getting lost and confused between learning to send the updates back via SSE and how to trigger the execution of tasker.php (and in some cases sending parameters to it, like .ajax() enables me to do).
Any help clearing this out would be appreciated.
UPDATE #2: Found this example but as soon as the JavaScript loads it is triggered; I want to trigger execution when the button is clicked.
UPDATE #1: TO ADD SAMPLE CODE
(Please excuse the formatting, I'm posting this from the mobile App)
This is an abstract it of how I have it implemented right now:
<? php
$output ="";
/*dummy code*/
read_csv_file();
$output.= "Opened and read file<br/>"; //Step 1
parse_csv_file();
$output.= "CSV file successfully parsed"; //Step 2
delete_from_directory();
$output.= "CSV file successfully deleted"; //Step 3
insert_data_into_db();
$output.= "successfully inserted records into Database"; //Step 4
return $output;
?>
<div id="placeholder"></div>
<button id="button">Update</button>
//jQuery...
$('#button').on('click', function(){
.ajax({
url: 'tasker.php',
dataType: 'txt',
data: dataVariable,
success: function (data){
$('#placeholder').append(data);
});
});
//jQuery...
First, on the client-side:
var server = null;
$('#button').on('click', function(){
if(server)server.close();
server = new EventSource('tasker.php?x=123');
server.addEventListener('message', function(e){
process(e.data);
if(e.data >= 100){server.close();server=null;} //6
}, false);
});
Points:
You have to pass the parameter with GET
I've assumed a process() that will take your progress updates, and alter the web browser display, somehow.
If the button is pressed again, it closes any previous SSE connection, and starts a new one.
6: see #6 on the back-end code below
On the back-end, PHP pseudo-code:
<?php
//Process inputs here
//If using sessions close them here
$lastProgress = 0;
while(true){
$progress = ... //1
if($progress == $lastProgress)continue; //2
echo "data:$progress\n\n"; //3, 4
#ob_flush();flush(); //5
//if($progress >= 100)exit; //6
}
Points:
1: Get the progress (e.g. look at log file, poll a DB, etc.)
2: Don't waste bandwidth; only send back new progress
3: I'm assuming $progress can only be a number. If any chance it can be text, you need error-checking, or json-escaping!!
4: "data:" prefix, "\n\n" is the SSE protocol.
5: The PHP idiom to be sure it gets sent immediately.
6: An SSE back-end is an infinite loop: the whole PHP process gets killed by Apache when the browser closes the socket. With a progress meter, you want it to die once we know there will be no more progress, but this has to come from the client (if the server disconnects, the browser will think the socket died and will try to reconnect). That is why this line is commented out. See #6 in the client code.
As a final note, you could stick with Ajax, and listen to readyState 3 (also known as the comet technique). (That is how you make it work on browsers like IE11 and earlier; also the only way to be able to use POST.)(See my book, Data Push Apps With HTML5 SSE, for loads more on those topics.)
I have this ajax request to update my db.
function ajax_submit(){
var submit_val=$("#stato").serialize();
dest="plan/new_bp1.php";
$.ajax({
type: "POST",
url: dest,
data: submit_val,
success: function(data){
data1=data.split("|");
if(data1[0]=="Successo"){
$("#spnmsg").fadeTo(200,0.1,
function(){$(this).removeClass().addClass("spn_success").html(data1[1]).fadeTo(900,1)});
}else if(data1[0]=="Errore"){
$("#spnmsg").fadeTo(200,0.1,
function(){$(this).removeClass().addClass("spn_error").html(data1[1]).fadeTo(900,1)});
}
},
complete: function(){
setTimeout(function(){ $('.container').load('plan/home.php');},2000);
}
});
}
The called script will take long to perform since it has to select, elaborate and insert around 4.000 recors each time. What I do now is to add a spinner on the screen to give users a feedback that the request is working (triggered by AjaxStart and AjaxStop).
At the end of the call the complete function will echo what the php script will echo.
What I'd like to do is to have a counter that will update during the script execution where I can say something like "X records out of 4.000 processed"
On the script side I have no problem to calculate the number of processed records and the number of record overall.
How can I update my script to show the progress?
You have a couple of options.
1) Right when the request starts you can start polling a different endpoint that just serves out the number of records that have been processed, like #adeneo suggested. You don't have to write to a file every time a record is processed. You can just store it in memory and ensure that the route handler you have to handle requests coming in for the progress has access to that same memory.
2) Implement a websocket endpoint on your server that pushes out the number of processed records. Basically, on the server then, you will call that Websocket library code to push out the progress. You will also have to create a Websocket connection on the Javascript side, which is trivial, and listen for those messages.
I have a File which process many other files and may take upto 30mins to process. I do an AJAX request to the file in the front end. The file outputs to another temporary file regarding the percentage of completion. And when it finishes it outputs a success message as its own XML output (not to the tmp file).
The problem i am having is, when the processing time is small .. say max upto 3mins, the AJAX request (made through jQuery) stays alive. But a time out occurs when the processing takes longer time (above 4mins). And the AJAX connection is cut. How do i prevent it and make it stay alive till the browser is closed?
You won't be able to do that. Unless it is a comet server, that can keep the connection alive at the server side and when there is any update to the data, it pushes out the contents.
In your case, the only way i can think of is doing this:
function ajax_call () {
$.ajax({
url : 'get_file_processing_output.html',
success : function (response) {
check your response, if file processing is not finished, then call ajax_call() again
if it is finished, then just do whatever you need.
},
timeout : function () {
time out then directly call ajax_call() again, maybe with a time interval would be better
}
})
}
I have a success call back above in ajax, because i feel you should response something from your server side to tell the client that the processing is not yet done.