这一篇其实是由上一篇引申出来的。之前说到,勉勉强强实现了 PDF 和 PPT 文件转图片,但是转换需要一定的时间,而我这里是用户发起请求进行转换的,这部分时间不应该让用户一直等着,应该结束请求,把数据返回给用户,然后后台再慢慢执行这些转换操作。
最开始我是有两种想法的,第一种是比较传统的,做一个进度条给用户看,虽然一个文件稍微要几秒钟的等待时间,但是有了进度条之后也勉强能够接受;第二种就是我现在在实现的办法,即结束请求,把数据返回给前端,然后后台再默默地进行转换操作。这里我综合考虑了一下,选择了第二种实现方法。
有了想法的雏形之后,就开始疯狂搜索寻找可行的解决方法了。之前敲代码的时候偶尔也有这种需求,之前的解决方法是利用 crontab,定时执行某些操作,但是放在这里就不合适了,因为这里的任务是实时生成的,且只需要执行一次,而不是定时执行。不过顺着之前的思路,我发现了有一个东西说不定能够满足我的需求——crontab 的好朋友,at。at 和 crontab 的区别基本上就是,crontab 是周期性的,而 at 是一次性的。
本来喜气洋洋的,以为这么快就找到解决方法了,没想到用着用着发现了一个很致命的问题:at 只支持两种生成方式,一是先写一个 bash 脚本,然后添加到临时任务里去,大概像这样:
at -f commandFile now + 10 minutes
第二种方式是,在命令行中输入 at now + 10 minutes,然后再输入具体的指令,形成临时任务。
我寻寻觅觅了好久,仍然找不到能够通过 PHP 生成 at 临时任务的办法,奈何时间有限,只能放弃这个方法,另寻他径了。
我找到的第二个方法是 ThinkPHP5(我使用 PHP 框架)使用官方的插件 think-queue,在稍微了解了一下之后,觉这个东西非常不错,功能好像还蛮强大的,而且挺符合我目前的需求的,但是万万没想到,当我真正跑去用它的时候,出现了那么多的问题。第一,它的安装还挺麻烦的,一开始以为直接用 composer require 一下就可以了,结果还有版本问题,支持 TP5 的之有比较老的一些版本。第二,使用起来还是有点迷的,一方面是既没有找到官方的文档手册,没有找到合适的使用教程,另一方面是但是时间比较着急,没能静下心来研究。不过感觉这东西好像还是不错的,等这段时间期末考完了,打算再去认真研究研究。
上面两种方法皆宣告失败之后,我只能使用最最原始的办法了。话不多说,直接上代码吧:
//清除之前的缓冲内容ob_end_clean();//设置响应头连接状态为关闭header("Connection: close");//设置HTTP请求状态为200 OKheader("HTTP/1.1 200 OK");//返回数据格式header("Content-Type: application/json;charset=utf-8");//打开输出控制缓冲ob_start();//返回数据给前端echojson_encode($array);//下面输出http的一些头信息$size =ob_get_length();//返回输出缓冲区内容的长度header("Content-Length: $size");//输出当前缓冲,并关闭缓冲ob_end_flush();//输出PHP缓冲flush();//前端接收到数据,请求到此结束,之后的代码都在后台静默执行,前端也无法知道执行情况if (function_exists("fastcgi_finish_request")) { // yii或yaf默认不会立即输出,加上此句即可(前提是用的fpm) fastcgi_finish_request(); // 响应完成, 立即返回到前端,关闭连接}//设置客户端断开连接时是否中断脚本的执行ignore_user_abort(true);//设置请求时间为不限时set_time_limit(0);...这里写需要后台执行的代码//冲刷(flush)所有响应的数据给客户端,请求完全结束fastcgi_finish_request();
还是原始的办法好使,没遇到啥困难就把问题给解决了,但是总感觉这样子实现起来太丑了,等有空了还是再去找找更好的办法吧,暂时就这样应付一下好了。
另外,如果你有兴趣,或者是有问题想要与我探讨,欢迎来访问我的博客:https:mu-mu.cn/blog