如果您的任务是上传庞大的数据集或在服务器上处理它,同时将进度更新到服务器,您应该考虑使用某种作业架构,您可以在其中启动作业并使用其他脚本来完成在服务器上运行(例如缩放/处理图像等)。在这种情况下,您一次只做一件事,从而形成一个任务管道,其中有一个输入和一个最终处理的输出。
在管道的每一步,任务的状态都会在数据库中更新,然后可以通过目前存在的任何服务器推送机制将其发送给用户。运行一个处理上传和更新的脚本会给您的服务器带来负载并限制您(如果浏览器关闭怎么办,如果发生其他错误怎么办)。将流程划分为多个步骤后,您可以从上次成功的位置恢复失败的任务。
有很多方法可以做到这一点。但是整体流程是这样的
以下方法是我为个人项目所做的,该脚本非常适合将数千张高分辨率图像上传和处理到我的服务器,然后缩小为多个版本并上传到亚马逊 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);
在服务器端,您需要创建一些东西来跟踪任务,一个简单的 Jobs 架构,带有 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/
你可以阅读更多关于从服务器推送更新的信息Pushing updates from server
以上是一个概念性的解释,还有其他方法可以实现这一点,但在我的案例中,这是一个解决相当大任务的解决方案。