Я отправляю данные формы на PHP, используя ajax.upload для загрузки файла в облачное хранилище Google.
Javascript:
var ajax = new XMLHttpRequest();
//PROGRESS HANDLER
ajax.upload.addEventListener("progress", function(event) {
var percent = ((event.loaded / event.total) * 100);
console.info(Math.round(percent) + "% uploading... please wait");
}, false);
//COMPLETE HANDLER
ajax.addEventListener("load", function(event) {
console.info(event.target.responseText);
}, false);
//ERROR HANDLER
ajax.addEventListener("error", function(event) {
console.info("Upload Failed");
}, false);
//ABORT HANDLER
ajax.addEventListener("abort", function(event) {
console.info("Upload Aborted");
}, false);
ajax.open("POST", "api/storage.php");
ajax.send(formdata);
PHP:
$_SESSION['storedBytes'] = 0;
$_SESSION['fileSize'] = $file["size"];
$uploader = $bucket->getResumableUploader(
fopen($fileTmpLoc, 'r'),
[
'predefinedAcl' => 'publicRead',
'name' => $_POST['uniqueName'],
'resumable' => true,
'chunkSize' => 262144,
'uploadProgressCallback' => 'uploadProgress'
]
);
try {
$object = $uploader->upload();
} catch (GoogleException $ex) {
$resumeUri = $uploader->getResumeUri();
$object = $uploader->resume($resumeUri);
}
function uploadProgress($storedBytes)
{
if (isset($_SESSION['storedBytes'])) {
$_SESSION['storedBytes'] += $storedBytes;
} else {
$_SESSION['storedBytes'] = $storedBytes;
}
$storedBytes = $_SESSION['storedBytes'];
$totalSize = $_SESSION['fileSize'];
$_SESSION['progress'] = ($storedBytes*100)/$totalSize;
echo "Progress ".$_SESSION['progress'];
}
И я получаю правильное значение прогресса в функции uploadProgress, но как отправить это значение в ответ на запрос ajax асинхронно или как показать прогресс в этой ситуации.
Я бы подумал об использовании обещаний и отложенных вызовов в ваших вызовах ajax. Я постараюсь привести пример как можно скорее.






Я бы использовал обещания в ваших вызовах javascript ajax. Пример jQuery будет примерно таким:
// gets the state of the upload from the PHP server.
var getProgress = function(phpUrlForProgress){
return $.ajax({
url: phpUrlForProgress,
type: 'get'
});
};
var keepCheckingProgress = function(phpUrlForProgress){
var deferred = $.Deferred();
var intervalID = setInterval(function(){
getProgress(phpUrlForProgress).done(function(response){
console.info(response); // see what the response looks like.
// you might need to parse the response into JSON before your if () statement.
if (response.percentComplete === 100) {// You are done with the upload
clearInterval(intervalID); // stops the setInterval loop;
deferred.resolve(response);
} else {
// some code to display a progress bar or whatever.
}
});
}, 3000);// setInterval function repeats every 3 seconds until cleared.
return deferred.promise();
};
// initiates the upload.
$.ajax({
url: phpUrlForUpload,
type: 'post'
data: formdata
});
// now start checking for upload progress.
var finished = keepCheckingProgress();
$.when(finished).then(function(){
// do something now that the upload is 100% done
});
Обратите внимание, что у меня не было возможности протестировать этот код на наличие ошибок или ошибок, это просто для того, чтобы дать вам представление.
По сути, обещания - это способ навести некоторый порядок операций в Javascript, который является асинхронным. Это способ сказать, когда эта задача завершена, займитесь другой задачей.
Я считаю, что jQuery использует несколько иную реализацию Promise, чем другие библиотеки обещаний. Общий учебник по обещаниям можно найти в здесь.
не успех. Потому что keepCheckingProgress вызывается после завершения загрузки. Это не асинхронно.
хорошо, я исправлю это. Если переместить вызов keepCheckingProgress за пределы части .done() вызова ajax, который инициирует загрузку, он теперь будет срабатывать сразу после загрузки, не дожидаясь ответа на вызов ajax.
Возможный дубликат Индикатор выполнения загрузки PHP Ajax