I have a PHP script that is likely to take at least 10 seconds to run. I would like to display progress for it for the user.

我有一个PHP脚本,可能至少需要10秒才能运行。我想为用户显示它的进度。

In the executing class, I have a property $progress which is updated with the progress (in 1-100), and a method get_progress() (which's purpose should be obvious).

在执行类中,我有一个属性$progress(以1-100为单位),以及一个方法get_progress()(其目的应该很明显)。

The question is, how to update the <progress> element on the front end for the user to see?

问题是,如何更新前端的元素以供用户查看?

I think AJAX is the solution, but I just can not get my head around it. I can not get to the same object instance.

我认为AJAX是解决方案,但我就是想不出来。我无法到达相同的对象实例。

8 个解决方案

#1


36

If your task is to upload a huge data-set or process it on the server, while updating progress to the server you should consider going with some sort of jobs architecture, where you initiate the job and do it with some other script running on the server (for example scaling / processing images etc). In this you do one thing at a time, thus forming a pipeline of tasks where there is an input and a final processed output.

如果你的任务是上传一个巨大的气候资料或在服务器上处理它,而服务器更新进步你应该考虑使用某种形式的工作架构,在你开始工作,做到与其他脚本运行在服务器上(例如缩放/处理图片等)。在这种情况下,您一次只做一件事情,从而形成一个有输入和最终处理的输出的任务管道。

At each step of pipeline the status of task is updated inside the database which can then be sent to the user by any server-push mechanism which exists these days. Running a single script which handles uploads and updates puts load on your server and also restricts you (what if the browser closes, what if some other error occurs). When process is divided into steps you can resume a failed task from the point where it succeeded last.

在管道的每个步骤中,任务的状态都在数据库中更新,然后可以通过当前存在的任何服务器推送机制发送给用户。运行一个处理上载和更新的脚本会增加服务器的负载,也会限制服务器的负载(如果浏览器关闭,如果发生其他错误怎么办)。当流程被划分为步骤时,您可以从失败的任务最后成功的地方继续执行它。

There exists many ways to do it. But the overall process flow looks like this

有很多方法可以做到这一点。但是整个流程看起来是这样的

The following method is what I did for a personal project and this script held good for uploading and processing thousands of high resolution image to my server which then were scaled down into multiple versions and uploaded to amazon s3 while recognizing objects inside them. (My original code was in python)

下面的方法是我为一个个人项目所做的,这个脚本很好地将数千个高分辨率的图像上传到我的服务器,然后将这些图像缩小成多个版本,并上传到amazon s3,同时识别其中的对象。(我的原始代码是python语言)

Step 1 :

Initiate the transport or task

启动传输或任务

First Upload your content and then return a transaction id or uuid for this transaction immediately via a simple POST request. If you are doing multiple files or multiple things in the task, you may also want to handle that logic in this step

首先上传内容,然后通过一个简单的POST请求立即返回事务id或uuid。如果您在任务中执行多个文件或多个任务,您可能还希望在这一步中处理该逻辑

Step 2:

Do the job & Return the progress.

做好本职工作,回报进步。

Once you have figured out how transactions occur you can then use any server side push technology to send update packet. I would choose WebSocket or Server Sent Events whichever applicable falling back to Long Polling on un-supported browsers. A simple SSE method would look like this.

一旦您了解了事务是如何发生的,您就可以使用任何服务器端推送技术来发送更新包。我将选择WebSocket或Server发送事件,无论这些事件是否适用,都可以追溯到不支持的浏览器上的长轮询。一个简单的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);

On the server side, you will need to create something which keeps a track of the tasks, a simple Jobs architecture with job_id and progress sent to the db shall suffice. I would leave the job scheduling to you and the routing as well, but after that the conceptual code (for simplest SSE which will suffice the above code) is as follows.

在服务器端,您将需要创建一些跟踪任务的东西,只需使用job_id和发送到db的进度的简单作业体系结构。我将把作业调度留给您和路由,但是之后的概念代码(对于最简单的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);
}

?>

A good tutorial on SSE can be found here http://html5doctor.com/server-sent-events/

在这里可以找到关于SSE的一个很好的教程http://html5doctor.com/server-sent-events/

and you can read more about pushing updates from the server on this question Pushing updates from server

在这个问题上,您可以阅读更多关于从服务器推送更新的信息

The above was a conceptual explanation, there are other ways to achieve this but this was the solution that took care of a fairly huge task in my case.

上面是一个概念性的解释,还有其他的方法来实现这个但这是解决我的问题的方法。

更多相关文章

  1. PHP上传文件 Error 6解决方法
  2. 基于PHP的UUID/GUID/uniqid替换方法及其可靠性论述
  3. 有一种防弹的方法可以检测php字符串中的base64编码吗?
  4. PHP实现接口方法时出现致命错误
  5. php和django位于同一个lighttpd服务器上
  6. 将node.js服务器更改为Apache服务器
  7. PHP判断客户端是PCweb端还是移动手机端方法
  8. php isset和empty方法的区别
  9. 当我将它移动到另一台服务器时,计数器将无法工作

随机推荐

  1. Android DrawerLayout 侧边栏使用之道
  2. Android 打勾显示输入的密码
  3. Android 开发环境安装配置手册
  4. Android(安卓)MonkeyRunner测试NotePad例
  5. MainFest.xml android
  6. 20个Android游戏源码,…
  7. js 判读是iPhone还是Android
  8. android tween动画效果
  9. android在google map上画出导航路线图
  10. Android APN