У меня есть PHP-скрипт, который загружает большой файл через cURL и сообщает о ходе загрузки в середине клиенту через буферизацию вывода.
ob_start();
ob_flush();
flush();
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://example.com/big-video-file.mp4");
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, 'progress');
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
curl_close($ch);
echo 100;
ob_flush();
flush();
function progress($resource,$download_size, $downloaded, $upload_size, $uploaded) {
if ($download_size > 0) echo round(($downloaded / $download_size) * 100).',';
ob_flush();
flush();
}
Затем я могу получать обновления о ходе выполнения через клиент, прослушиваяonreadystatechange
для readyState
== 3.
let req = new XMLHttpRequest(), ta = document.querySelector('textarea');
req.open('GET', 'curl_progress.php?ajax=1');
req.addEventListener('readystatechange', function() {
if (req.readyState == 3) { //we get here repeatedly - yay!
let spl = req.responseText.split(',');
ta.value += spl[spl.length-2]+'\n';
} else if (req.readyState == 4 && req.status == 200)
ta.value += 100;
}, false);
req.send();
Это прекрасно работает.Не волнуйся о том, как я справляюсь с последними достижениями;Дело в том, что readyState
== 3 происходит неоднократно.
Теперь мой вопрос: почему это не работает с загрузкой?
Я адаптировал скрипт длясделать загрузку вместо.Опять же, сторона PHP работает нормально.Я вижу, как он выплевывает информацию отслеживания через буферизацию вывода.Вот адаптированный запрос cURL для загрузки, а не для загрузки:
$ch = curl_init($_SESSION['vimeo_upload_url']);
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_POST => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_INFILE => fopen($_FILES['file']['tmp_name'], 'r'),
CURLOPT_INFILESIZE => $_FILES['file']['size'],
CURLOPT_UPLOAD => true,
CURLOPT_PROGRESSFUNCTION => 'curl_progress',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_NOPROGRESS => false,
CURLOPT_SSL_VERIFYPEER => false
]);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Tus-Resumable: 1.0.0',
'Upload-Offset: 0',
'Content-Type: application/offset+octet-stream'
]);
function curl_progress($resource, $download_size, $downloaded, $upload_size, $uploaded) {
if ($upload_size > 0) echo round(($uploaded / $upload_size) * 100).',';
ob_flush();
flush();
}
Сама загрузка отлично работает - проблем нет.
Но на клиенте readyState
== 3срабатывает только один раз - незадолго до того, как все завершится.
let req = new XMLHttpRequest(), fd = new FormData();
fd.append('file', input.files[0]);
req.open('POST', '../vimeo_upload.php?action=transfer_file');
req.addEventListener('readystatechange', function() {
if (this.readyState == 3) { //we get here only once!
let spl = this.responseText.split(',');
console.log(spl[spl.length-2]);
} else if (this.readyState == 4 && this.status == 200)
console.log(100);
}, false);
Кто-нибудь знает, почему это так, то есть почему я не могу заставить его срабатывать несколько раз, как это было для загрузки?