AJAX - 如何获得readystate == 3反复上传以进行上传?

时间:2018-05-22 13:36:55

标签: javascript php ajax curl xmlhttprequest

我有一个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);

有没有人知道为什么会这样,也就是说为什么我不能像下载一样多次点击它?

0 个答案:

没有答案