Fundamentally, your problem lies in determining how long it will take the server to respond to your request. The problem with the solutions that depend on Xmlhttprequest is that you can only measure the upload time of the request, that is, how long it would take your computer to upload the file. csv to the server (for example).
How will I predict how long the requisition will take ?
Your best chance is by trial and error in determining an approximable formula f(x) = t
where x
would be the number of lines in the file and t
the time it would take your server to process such a request.
Even so, you would be subject to need at least 2 separate requests for PHP to answer the number of lines in the file before you start processing it OR do this count in Javascript (both bad solutions).
Still in that line of reasoning, if one day when you switch server¹, your formula may be declared wrong in case of incompatibility. Processors, Memories or hard disk with greater efficiency will take different times to process the same algorithm. The same goes for upgrading server applications, OS update or PHP versions that influence performance.
Note¹: In case of shared server rents, the machine can be changed without you being notified.
Is there any way to make onprogress to pick up the progress of the request ?
There’s a difference between sending the request and response time. It can even be relatively easy to calculate the size (in bytes) of your request and determine when it will end, but this only takes into account the first step of the process (sending the request). The response time cannot be discovered at the time the request occurs.
If yes this break in multiple requests can affect traffic( why depending on the size of the task will take and cost several requests)?
I don’t quite understand what you mean here, but you are referring to sending 1 line at a time (by ajax request) just for the pleasure of building a Progress bar faithful, I strongly recommend that you do not. This could generate a very high number of resource consumption totally unnecessary. Keep in mind that once you upload an entire file, there has been processing on the client machine until the request reaches the server, processing the web server and then initializing your application in PHP. If each line in the file is handled in a separate request, you will be using your web server to initialize the same PHP application several times unnecessarily.
Is there any other recommended way to make progressBar?
There is an option theoretically valid which suggests multiple requests for ask the server about the progress of the main request. However, I believe such an option is only possible if your main request is long enough. The process would consist of something that would respect some rules:
- Executes the main request.
- Update an information shareable on the progress of the request from time to time.
- Create a loop in the frontend that executes a request specific to each
x
times
- This secondary request would be able to read the same information that the main request is updating from time to time.
The server consumption would be depending on the variable x
that you would determine to ask the server for progress. The response of such a request would be able to offer you information as reliable as you could measure progress within your main code (main request).
Update
Using the repository as a basis jQuery-Ajax-Progress for englercj, I was able to implement the concept I presented as theoretical. What should be taken into consideration are the following items:
- Each time you "interrupt" the main process to save the progress (in this case, setProgress function within the loop), your main request generates extra processing and takes longer.
- Each request the client makes to the server affects the performance of your server.
- This is a highly simple example for the sole purpose of teaching, as I use the server file system to save progress (hard disk access is very slow!)
You can clone my repository on https://github.com/deleugpn/jquery-ajax-progress or follow the following snippets (or check an online demo here http://solucoesideais.com.br/dev/progressbar/demo.html)
Note: If your request php status. is awaiting the end of Progress.php in order to be triggered, your problem may be in your browser not authorizing the call.
Progress.php
This is the file that contains your main request.
ini_set('max_execution_time', 60);
// The bigger this number, the longer the request will take
$max = 100000000;
/**
* Store the current progress in a file to be read by status.php
* @param $progress
*/
function setProgress($progress) {
$file = __DIR__ . '/p';
if (!is_file($file))
touch($file);
file_put_contents($file, $progress);
}
// Loop to delay the request a lot
for ($i = 0; $i < $max; $i++) {
/**
* Each 100'000 runs, the progress will be "recorded"
* This is where you should learn what number is good for your loop that won't affect
* the requests' performance.
*/
if ($i % 100000 === 0) {
setProgress(($i * 100) / $max);
}
}
echo true;
php status.
This is the file that will tell you how your main request is going.
// Make a request to another domain so browser doesn't block you
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
if (is_file(__DIR__ . '/p')) {
echo file_get_contents(__DIR__ . '/p'); // Note: if the file is busy (being rewritten, this will result in nothing.
} else {
echo 0;
}
demo html.
This is the progress bar demo file.
<!DOCTYPE html>
<html>
<head>
<title>Ajax Progress</title>
<!-- Meta -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico"/>
<!-- Google CDN -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js"></script>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/black-tie/jquery-ui.css"/>
<!--<script src="js/jquery.ajax-progress.js"></script>-->
<script>
var request = {
checkStatus: function () {
$.ajax({
method: 'GET',
url: 'server/status.php',
dataType: 'json',
success: function (data) {
if(data)
request.setStatus(data);
}
});
},
setStatus: function (status) {
$('#prog')
.progressbar('option', 'value', status)
.children('.ui-progressbar-value')
.html(status.toPrecision(3) + '%')
.css('display', 'block');
},
_interval: null,
clearInterval: function () {
clearInterval(request._interval);
}
};
$(function () {
$('#prog').progressbar({value: 0});
request._interval = setInterval(request.checkStatus, 1000);
$.ajax({
method: 'GET',
url: 'server/progress.php',
dataType: 'json',
success: function () {
request.clearInterval();
request.setStatus(100);
},
error: function () {
request.setStatus(0);
request.clearInterval();
console.log('AWWW! Error!!');
}
});
});
</script>
</head>
<body>
<div id="prog"></div>
</body>
</html>
I was going to offer a reward for this question, I need an urgent solution, I am using a method mequetrefe that gives to shame rsrsrs. I’m also testing the other answers!
– Junior Moreira
@Júniormoreira and the author, updated my answer to demonstrate a functional example, however it is easy to notice from my explanation that it is a complicated process and may not be worth the effort.
– Marco Aurélio Deleu
Have you been able to implement the load bar? Have further questions?
– Marco Aurélio Deleu
@Marcoauréliodeleu not yet, I’m trying to ensure that all my import is working so that later I worry about the progressibar part, I thought it would be fast but are several validations
– Gabriel Rodrigues