在进度元素上显示 AJAX 上载状态步骤 1 :第 2 步:
我有一个 AJAX 脚本,用于将文件上传到 PHP 脚本,该脚本可能需要至少 10 秒才能运行。我想为用户显示它的进度。
在执行类中,我有一个随进度更新的属性(在1-100中)和一个方法(其目的应该是显而易见的)。$progress
get_progress()
问题是,如何更新前端的元素供用户查看?<progress>
我认为AJAX是解决方案,但我就是无法理解它。我无法到达相同的对象实例。
我有一个 AJAX 脚本,用于将文件上传到 PHP 脚本,该脚本可能需要至少 10 秒才能运行。我想为用户显示它的进度。
在执行类中,我有一个随进度更新的属性(在1-100中)和一个方法(其目的应该是显而易见的)。$progress
get_progress()
问题是,如何更新前端的元素供用户查看?<progress>
我认为AJAX是解决方案,但我就是无法理解它。我无法到达相同的对象实例。
我会把它放在这里作为任何搜索者的参考 - 这完全依赖于任何javascript。
<?php
/**
* Quick and easy progress script
* The script will slow iterate through an array and display progress as it goes.
*/
#First progress
$array1 = array(2, 4, 56, 3, 3);
$current = 0;
foreach ($array1 as $element) {
$current++;
outputProgress($current, count($array1));
}
echo "<br>";
#Second progress
$array2 = array(2, 4, 66, 54);
$current = 0;
foreach ($array2 as $element) {
$current++;
outputProgress($current, count($array2));
}
/**
* Output span with progress.
*
* @param $current integer Current progress out of total
* @param $total integer Total steps required to complete
*/
function outputProgress($current, $total) {
echo "<span style='position: absolute;z-index:$current;background:#FFF;'>" . round($current / $total * 100) . "% </span>";
myFlush();
sleep(1);
}
/**
* Flush output buffer
*/
function myFlush() {
echo(str_repeat(' ', 256));
if (@ob_get_contents()) {
@ob_end_flush();
}
flush();
}
?>
如果你的任务是上传一个巨大的数据集或在服务器上处理它,在更新到服务器的进度时,你应该考虑使用某种作业架构,在那里你启动作业并使用服务器上运行的其他脚本来完成它(例如缩放/处理图像等)。在这种情况下,您一次只做一件事,从而形成一个任务管道,其中有输入和最终处理的输出。
在管道的每个步骤中,任务的状态都在数据库中更新,然后可以通过现在存在的任何服务器推送机制将其发送给用户。运行处理上载和更新的单个脚本会给服务器带来负载,也会限制您(如果浏览器关闭怎么办,如果发生其他错误怎么办)。将流程划分为多个步骤后,您可以从上次成功时恢复失败的任务。
有很多方法可以做到这一点。但整个流程流程如下所示
以下方法是我为个人项目所做的,此脚本非常适合将数千张高分辨率图像上传和处理到我的服务器,然后将其缩小为多个版本并上传到amazon s3,同时识别其中的对象。(我的原始代码是用python编写的)
启动传输或任务
首先上传您的内容,然后通过简单的 POST 请求立即返回此交易的交易 ID 或 uuid。如果要在任务中执行多个文件或多个操作,则可能还需要在此步骤中处理该逻辑
完成工作并返回进度。
一旦你弄清楚了交易是如何发生的,你就可以使用任何服务器端推送技术来发送更新数据包。我会选择WebSocket或Server Sent Events,无论哪个适用,都可以在不受支持的浏览器上回退到Long Polling。一个简单的 SSE 方法将如下所示。
function TrackProgress(upload_id){
var progress = document.getElementById(upload_id);
var source = new EventSource('/status/task/' + upload_id );
source.onmessage = function (event) {
var data = getData(event); // your custom method to get data, i am just using json here
progress.setAttribute('value', data.filesDone );
progress.setAttribute('max', data.filesTotal );
progress.setAttribute('min', 0);
};
}
request.post("/me/photos",{
files: files
}).then(function(data){
return data.upload_id;
}).then(TrackProgress);
在服务器端,您需要创建一些跟踪任务的东西,一个简单的Jobs架构,其中包含发送到db的job_id和进度就足够了。我会把作业调度留给你和路由,但之后的概念代码(对于最简单的SSE,这将足以满足上述代码)如下。
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
/* Other code to take care of how do you find how many files are left
this is really not required */
function sendStatusViaSSE($task_id){
$status = getStatus($task_id);
$json_payload = array('filesDone' => $status.files_done,
'filesTotal' => $status.files_total);
echo 'data: ' . json_encode( $json_payload ) . '\n\n';
ob_flush();
flush();
// End of the game
if( $status.done ){
die();
}
}
while( True ){
sendStatusViaSSE( $request.$task_id );
sleep(4);
}
?>
可以在此处找到有关SSE的好教程 http://html5doctor.com/server-sent-events/
您可以阅读有关从服务器推送更新的更多信息,此问题从服务器推送更新
以上是一个概念性的解释,还有其他方法可以实现这一点,但这是我的情况下处理相当艰巨任务的解决方案。