AJAX - как заставить readystate == 3 многократно запускаться для загрузки? - PullRequest
0 голосов
/ 22 мая 2018

У меня есть 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);

Кто-нибудь знает, почему это так, то есть почему я не могу заставить его срабатывать несколько раз, как это было для загрузки?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...