如果你的任务是上传一个巨大的数据集或在服务器上处理它,同时更新进度到服务器,你应该考虑采用某种作业架构,在那里你启动作业,并与一些其他脚本运行在服务器(例如缩放/处理图像等)。在这里,你一次做一件事,从而形成一个任务的管道,其中有一个输入和最终的处理输出。
在流水线的每个步骤,任务的状态在数据库内被更新,然后可以通过任何存在于这些天的服务器推送机制发送给用户。运行处理上传和更新的单个脚本会在您的服务器上放置负载,并限制您(如果浏览器关闭,如果发生其他错误会发生什么)。当过程分为步骤时,可以从最后成功的点继续失败的任务。
有很多方法可以做到。但整个流程看起来像这样
以下方法是我为个人项目做的,这个脚本适合上传和处理成千上万的高分辨率图像到我的服务器,然后缩小到多个版本,并上传到亚马逊S3,同时识别其中的对象。 (我的原代码是在python)
步骤1 :
启动传输或任务
首先上传您的内容,然后通过简单的POST请求立即返回此事务的事务ID或uuid。如果您在任务中执行多个文件或多个任务,您可能还需要在此步骤中处理该逻辑
第2步:
做工作&返回进度。
一旦你弄清楚事务如何发生,你可以使用任何服务器端推技术发送更新数据包。我会选择WebSocket或服务器发送事件,适用时,回退到不支持的浏览器上的长轮询。一个简单的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);
在服务器端,您将需要创建一些跟踪任务的任务,具有job_id和进度发送到db的简单Jobs架构就足够了。我将离开作业调度给你和路由,但之后,概念代码(对于最简单的SSE,将足以满足上述代码)如下。
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);
}
?>
并且您可以阅读关于在此问题Pushing updates from server上从服务器推送更新的更多信息
上面是一个概念性的解释,还有其他方法来实现这一点,但这是解决方案,在我的情况下,照顾了一个相当大的任务。