What I am trying to do is upload the file/files information to upload.php
using ajax, then uploading the same information again to a remote server by curl to remoteUpload.php
. Finally in remoteUpload.php
file I perform the actual upload of the file/files.
When doing the first step -> upload the file/files information to upload.php
I display a progress bar of this step using ajax.
But the when doing the second step -> upload the same information again to remote server using curl to remoteUpload.php
the progress bar is not displayed, and this is my problem.
How to display the progress bar for second step by ajax ?
Javascript:
var upload_btn = document.getElementById('upload_file');
var result = document.getElementById('result');
upload_btn.onclick = function () {
var uploadInput = document.getElementsByName('file[]')[0];
if (uploadInput.files.length > 0) {
console.clear();
var ajax = new XMLHttpRequest();
var inputFileData = formData(uploadInput);
ajax.onreadystatechange = function () {
if (ajax.readyState == 4 && ajax.status == 200) {
var json = JSON.parse(ajax.responseText);
result.innerHTML = json.text;
}
};
ajax.upload.addEventListener('progress', function (e) {
result.innerHTML = Math.round(e.loaded / e.total * 100) + "%";
});
ajax.open("post", "upload.php");
ajax.send(inputFileData);
}
};
function formData(inputFileObj) {
var formData = new FormData;
var inputFile = inputFileObj.files;
if (inputFile.length > 0) {
for (i = 0; i < inputFile.length; i++) {
formData.append(inputFileObj.name, inputFile[i]);
}
}
return formData;
}
PHP: (upload.php)
function progressCallback($dltotal, $dlnow, $ultotal, $ulnow) {
static $last;
$progress = @round($ulnow / $ultotal * 100);
if($last < $progress) echo json_encode(array('text' => $progress));
flush();
$last = $progress;
}
if (strtolower($_SERVER['REQUEST_METHOD']) == 'post' && !empty($_FILES)) {
foreach ($_FILES['file']['tmp_name'] as $index => $tmpFileName) {
if ($_FILES['file']['error'][$index] > 0) {
$text = "A file did not uploaded correctly.";
return false;
}
$ch = curl_init("http://serverfiles/remoteUpload.php");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, 'progressCallback');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, array('fileupload' => '@' . $tmpFileName));
$text = curl_exec($ch);
}
}
echo json_encode(array('text' => $text));
exit;
PHP: (remoteUpload.php)
if (move_uploaded_file($_FILES['fileupload']['tmp_name'], "files/" . $_FILES['fileupload']['name']))
echo "The file has been uploaded.";
else
echo "error";
You can save in progressCallback()
to $_SESSION
your $progress
and from js side after "first step" upland complete run setIntevral(/*ajax*/)
make ajax
requests to server get $_SESSION['progress]
and display second progress bar(or load first progress barr till 50% and continue load second 50%) in your form and when it complete call clearInterval()
DETAILED ANSWER
Explanation: we will count progress in following logic. If we have uploaded 5 files at once (as in your case seems uploaded was multi file) then we will divide 100%
by 5
and will increase by 25%
progress during one file curl submit, for this you need following 5 modifications
1) call somewhere above session_start()
in your upload.php
if it not done
2) save to session total files count and current processing file index
// Saveing total amount of uploaded files
$_SESSION['UP_total_count'] = count($_FILES['file']);
foreach ($_FILES['file']['tmp_name'] as $index => $tmpFileName) {
...
// Saving current index of uploaded file
$_SESSION['UP_current_index'] = ($index+1);//+1 as it starts from 0
}
3) save in progressCallback
function current progress number in 0-100
format
function progressCallback($dltotal, $dlnow, $ultotal, $ulnow) {
...
$_SESSION['UP_current_progress'] = $progress;
}
4) create new getUploadProgress.php
and return json encoded progress infromation from session
session_start();
echo json_encode( array(
'total_count' => $_SESSION['UP_total_count'],
'current_index' => $_SESSION['UP_current_index'],
'current_progress' => $_SESSION['UP_current_progress'],
) );
5) add in your ajax.onreadystatechange
setInteval
function call, and define in your js global variable progressSetInterval
....
var progressSetInterval = null;// Global
ajax.onreadystatechange = function () {
if (ajax.readyState == 4 && ajax.status == 200) {
...
progressSetInterval = setInterval(function(){
$.ajax({
type: "POST",
url: "getUploadProgress.php",
success: function(data){
// Calculating progress based on 100 25 logic explained above
var progressPart = 100 / data['total_count'];
var currProgress =
(data['total_count'] - data['current_index']) * progressPart;
currProgress += (progressPart/100) * data['current_progress'];
// You can display progress somehow, apped to div or show prgoress...
console.log( "Second progress: " + currProgress);
// if currProgress is 100% removing setinterval
if( currProgress >= 100 ){
clearInterval( progressSetInterval );
}
},
dataType: 'json'
});
}, 1000);
}
};
NOTE: during usage of this example code of course there will be needed additional rounds
, JS/PHP functions
addition, variable adjustments or some logical adjustments for more effectiveness, but basically this is logic of one option which you can use
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With