实时交互 - 请问PHP脚本执行时如何实时提供反馈

php中文网
发布: 2016-06-06 20:40:28
原创
1442人浏览过

有两个页面一个上传excel文件,另一个接受这个excel文件并处理,下面是这个页面处理时显示的内容,可是每次都要等程序完全运行才会显示。有时候时间太长没有反馈,用户会关闭页面,我想增加实时提示。求大家指点下

我想过用异步的方法,可第二个文件是在Ifram框架内的,异步获取也是要等待值的,最终显示还是一样。

//117条数据读取插入并且生成报表
11:04:17 开始读取EXCEL表。
11:04:31 读取并插入数据库成功
11:04:31 完成工作簿添加一个工作表。
11:04:32 完成工作表内容写入。
11:04:32 完成工作表克隆。
11:04:32 完成克隆工作表【失业】添加。
11:04:33 完成工作表克隆。
11:04:33 完成克隆工作表【医疗】添加。
11:04:33 完成工作表克隆。
11:04:33 完成克隆工作表【工伤】添加。
11:04:34 完成工作表克隆。
11:04:34 完成克隆工作表【生育】添加。
11:04:34 完成工作表克隆。
11:04:34 完成克隆工作表【重大疾病】添加。
11:04:35 完成工作表克隆。
11:04:35 完成克隆工作表【补充医疗】添加。
11:04:35 设置文件基本信息。
11:04:35 查询结果集数据库成功。
11:04:35 查询结果集转化为数组成功。
11:04:35 完成工作簿[养老]数据填入。
11:04:36 完成工作簿[失业]数据填入。
11:04:36 完成工作簿[医疗]数据填入。
11:04:36 完成工作簿[工伤]数据填入。
11:04:37 完成工作簿[生育]数据填入。
11:04:37 完成工作簿[重大疾病]数据填入。
11:04:38 完成工作簿[补充医疗]数据填入。
11:04:46 完成工作簿文件创立。
登录后复制

回复内容:

有两个页面一个上传excel文件,另一个接受这个excel文件并处理,下面是这个页面处理时显示的内容,可是每次都要等程序完全运行才会显示。有时候时间太长没有反馈,用户会关闭页面,我想增加实时提示。求大家指点下

我想过用异步的方法,可第二个文件是在Ifram框架内的,异步获取也是要等待值的,最终显示还是一样。

//117条数据读取插入并且生成报表
11:04:17 开始读取EXCEL表。
11:04:31 读取并插入数据库成功
11:04:31 完成工作簿添加一个工作表。
11:04:32 完成工作表内容写入。
11:04:32 完成工作表克隆。
11:04:32 完成克隆工作表【失业】添加。
11:04:33 完成工作表克隆。
11:04:33 完成克隆工作表【医疗】添加。
11:04:33 完成工作表克隆。
11:04:33 完成克隆工作表【工伤】添加。
11:04:34 完成工作表克隆。
11:04:34 完成克隆工作表【生育】添加。
11:04:34 完成工作表克隆。
11:04:34 完成克隆工作表【重大疾病】添加。
11:04:35 完成工作表克隆。
11:04:35 完成克隆工作表【补充医疗】添加。
11:04:35 设置文件基本信息。
11:04:35 查询结果集数据库成功。
11:04:35 查询结果集转化为数组成功。
11:04:35 完成工作簿[养老]数据填入。
11:04:36 完成工作簿[失业]数据填入。
11:04:36 完成工作簿[医疗]数据填入。
11:04:36 完成工作簿[工伤]数据填入。
11:04:37 完成工作簿[生育]数据填入。
11:04:37 完成工作簿[重大疾病]数据填入。
11:04:38 完成工作簿[补充医疗]数据填入。
11:04:46 完成工作簿文件创立。
登录后复制

非常感谢大家的回答,我用的是提交页面控制一个进度条,按下按钮进度条开始激活,设置一个大于用户完成操作的时间,当另一个页面处理完成时,计算出这个进度条未布满的部门,用额外5S 控制进度条速度填满

立即学习PHP免费学习笔记(深入)”;

function flush_buffers()
{
    ob_end_flush();
    ob_flush();
    flush();
    ob_start('ob_callback');
}

function ob_callback($buffer)
{
    return $buffer . str_repeat(' ', max(0, 4097 - strlen($buffer)));
}
登录后复制

demo

echo '<br>处理1!<br>';
flush_buffers();

//do ....

echo '<br>处理2!<br>';
flush_buffers();
登录后复制

拓展:
PHP5.4上传进度支持(Upload progress in sessions)

题主问的应该是实时输出的问题,一般情况下一个php脚本在全部执行完毕后,才会将脚本输出一次性返回,而在执行过程中的输出内容是没有办法实时获取的,这种行为叫输出缓存,可以通过output.buffering(PHP手册)来开关

<?php
echo 1;
sleep(1);
echo 2;
登录后复制

访问这个页面,会在header内容全部输出1秒后,同时输出12

但在程序中可以通过flush强制将缓存内容输出并清空缓存

<?php
echo 1;
flush();
sleep(1);
echo 2;
登录后复制

加上flush之后,一般情况下1会在header返回后立即输出,1秒之后,再输出2

为什么是一般情况下呢,因为php的缓存是刷新了,但是如果前端web服务器(如apache)开启了gzip/deflate/cache等需要等待脚本输出完毕才能执行的功能,会被再一次缓存

如果真的需要这样的实时输出功能,需要把整个response链路上所有的缓存功能全部关闭,其实是有些得不偿失的~

算家云
算家云

高效、便捷的人工智能算力服务平台

算家云 228
查看详情 算家云

http://php.net/manual/zh/function.flush.php

我能想到的有两种办法,都是用AJAX异步的:

  1. 将每一个步骤都分成一个函数然后URL传参执行对应函数,比如step=first对应运行first()函数,运行成功返回你的内容。前端这边用AJAX请求,如果成功返回则append内容到页面上然后再继续请求下一步这样一直递归下去直至任务完成。可以参考我给Typecho写的在线升级插件,使用的就是这种方法。

  2. 这种方法就比较简单了PHP每次运行完一步就把内容append到一个JSON文件中,前端这边用AJAX轮询请求这个JSON文件并显示到页面上。

上传进度如 @宋小北 所说,鸟哥的博客中说的很明确:

1、PHP5.4之前,APC通过apc.rfc1867_freq string选项原生支持文件上传的缓存更新,参考 http://php.net/manual/zh/apc.configuration.php#ini.apc.rfc1867
2、PECL也有扩展实现上传进度 http://pecl.php.net/package/uploadprogress

如果你用较早版本,又不想搞上述劳什子,就用 Flash 上传组件如swfupload或者jQuery File Upload之类。

上传完成后实时显示处理结果,你可以关闭Web Server 和 PHP的各种buffer,然后靠flush()强制输出。但这是一个愚蠢的做法。
给一个简单思路,每处理一步就向第三方存储比如memcached,redis,甚至是文件里写入一个标记,通过ajax轮询这个标记,准实时更新dom里的内容。这应该是比较折衷比较理想的方案。恁看中不中?

====

@公子 老师指点了一下,我发现他的第一个方案把操作拆成几步来做更好,处理大文件时可以防止超时。同时要注意很多问题,比如文件状态维护防止漏操作,每一步都要重复读文件等等...我只是吃饭前来SG逗个乐子,具体的细节还是题主自己考虑吧。

将程序放在队列中处理,将执行日志放到数据库或者文本,然后通过ajax轮询获取和处理进度并显示

我专门的写了个解决方案的文章,去看看:http://segmentfault.com/a/1190000004235213

相关标签:
php
PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号