javascript - 如何将curl上传进度发送给ajax显示

标签 javascript php ajax curl progress-bar

我想做的是使用 ajax 将文件/文件信息上传到 upload.php,然后通过 curl to 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;
}

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;

PHP: (remoteUpload.php)

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

最佳答案

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


详细答案

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

1) 如果未完成,请在 upload.php 中调用 session_start() 上方的某处

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

// 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
}

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

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

4) 创建新的 getUploadProgress.php 并从 session 中返回 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'],
) );

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);
        }
};

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

关于javascript - 如何将curl上传进度发送给ajax显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34313894/

相关文章:

javascript - Sequelize 通过另一个多个关联项查询所有关联项

JavaScript 将数组的一项移到前面

javascript - 通过 Json 传输表单数据

javascript - 我可以使用在线表单自动填充 HTML 页面而不使用数据库吗?

php - 通过范围解析运算符调用非静态方法

php - 以数据流的形式写入div

javascript - 使用javascript更改div布局

php - fatal error : Call to a member function format () on boolean

javascript - Dojo XHR 根本不向其他服务器发送请求,但 jQuery 中一切正常

javascript - 为什么 UpdatePanel 会在几分钟后停止工作?