如何将 curl 上传进度发送到要显示的 ajax
Posted
技术标签:
【中文标题】如何将 curl 上传进度发送到要显示的 ajax【英文标题】:How to send curl upload progress to ajax to be displayed 【发布时间】:2016-03-22 16:47:47 【问题描述】:我要做的是使用 ajax 将文件/文件信息上传到 upload.php
,然后通过 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;
PHP:(上传.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";
【问题讨论】:
【参考方案1】:您可以将progressCallback()
保存到$_SESSION
您的$progress
并在“第一步”完成后从js 端运行setIntevral(/*ajax*/)
向服务器发出ajax
请求获取$_SESSION['progress]
并显示第二个进度条(或在表单中加载第一个进度条直到 50% 并继续加载第二个 50%),当它完成调用 clearInterval()
详细解答
说明:我们将按照以下逻辑计算进度。如果我们一次上传了 5 个文件(在您的情况下似乎上传的是多个文件),那么我们将 100%
除以 5
并在一个文件 curl 提交期间增加 25%
进度,为此您需要以下 5修改
1)如果未完成,请在您的upload.php
中的session_start()
上方的某处调用
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
3)以0-100
格式保存progressCallback
函数当前进度号
function progressCallback($dltotal, $dlnow, $ultotal, $ulnow)
...
$_SESSION['UP_current_progress'] = $progress;
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'],
) );
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);
;
注意:在使用这个示例代码的过程中,当然需要额外的rounds
,JS/PHP functions
添加,变量调整或者一些逻辑调整以获得更有效,但基本上这是逻辑您可以使用的一个选项
【讨论】:
谢谢,但是如何在我的代码上应用你的话? 好的,我已经尝试尽可能匹配,在基本示例中解释它,在详细答案之后检查代码 很遗憾,没有出现进度,而是等到完成,然后直接100%打印。 实际上从这一点上我帮不了你,你也不应该用新代码更新你的问题或创建 php fiddle,你也不应该调试它在 php 和 js 的不同位置进行转储以查看什么在会话中你在 js 中得到了什么进度计算 js 等等......或者你可以把日志记录在 php 文件中(为了不中断上传流转储和退出)例如你可以输入progressCallback
这个日志file_put_content("PATH/progress.log", json_encode($progress)."\n", FILE_APPEND);
以上是关于如何将 curl 上传进度发送到要显示的 ajax的主要内容,如果未能解决你的问题,请参考以下文章