如何将curl上传进度发送到要显示的ajax

Lio*_*ing 9 javascript php ajax curl progress-bar

我要做的是将文件/文件信息upload.php上传到使用ajax,然后通过curl将相同的信息再次上传到远程服务器remoteUpload.php.最后在remoteUpload.php文件中我执行文件/文件的实际上传.

在执行第一步时 - >上传文件/文件信息到upload.php我使用ajax显示此步骤的进度条.

但是当第二步 - >使用curl再次向远程服务器上传相同的信息到remoteUpload.php进度条时,不会显示,这是我的问题.

如何通过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;
}
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

PHP:(remoteUpload.php)

if (move_uploaded_file($_FILES['fileupload']['tmp_name'], "files/" . $_FILES['fileupload']['name']))
    echo "The file has been uploaded.";
else
    echo "error";
Run Code Online (Sandbox Code Playgroud)

Arm*_*men 2

您可以在表单中的“第一步”高地完成运行后向progressCallback()服务器$_SESSION发出请求以获取并显示第二个进度条(或加载第一个进度条直到 50% 并继续加载第二个 50%),然后从 js 端保存到它完成通话$progresssetIntevral(/*ajax*/)ajax$_SESSION['progress]clearInterval()


详细解答

说明:我们将按照以下逻辑计算进度。如果我们一次上传了 5 个文件(在您的情况下似乎上传的是多个文件),那么我们将在一个文件curl 提交期间100%除以5并增加25%进度,为此您需要进行以下 5 项修改

1)如果没有完成,请调用上面session_start()的某个地方upload.php

2)保存到会话总文件数和当前处理文件索引

// 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
}
Run Code Online (Sandbox Code Playgroud)

3)以格式保存progressCallback函数当前进度号0-100

function progressCallback($dltotal, $dlnow, $ultotal, $ulnow) { 
    ...
    $_SESSION['UP_current_progress'] = $progress;
}
Run Code Online (Sandbox Code Playgroud)

4)创建新的getUploadProgress.php并从会话返回 json 编码的进度信息

session_start();
echo json_encode( array(
   'total_count' => $_SESSION['UP_total_count'],
   'current_index' => $_SESSION['UP_current_index'],
   'current_progress' => $_SESSION['UP_current_progress'],
) );
Run Code Online (Sandbox Code Playgroud)

5)添加你的ajax.onreadystatechange setInteval函数调用,并在你的js全局变量中定义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);
        }
};
Run Code Online (Sandbox Code Playgroud)

注意:在使用此示例代码期间,当然需要进行额外的roundsJS/PHP functions添加的、变量调整或一些逻辑调整以提高效率,但基本上这是您可以使用的一个选项的逻辑