最近业务中碰到一个问题, 就是需要用 PHP 去上传一个大文件, 大小差不多一个 G, 这可就为难我了, 因为大文件上传一直是个老大难的问题, 不过最近骚操作一波还是可以愉快的实现的, 下面简单说下如何实现
关键字: wget,PHP 后台执行脚本
首先给大家介绍下 wget 命令, 这个命令我之前都是用来下载用的, 不过 wget 还有一个功能, 就是可以断点续传, 那一个大文件想要安全且稳定的上传, 断电续传的加入必不可少, 为什么选用 wget, 主要还是因为 wget 基本每台机器都会装, 不需要做太多运维的工作, 简单看下命令
wget -c -t 10 -T 120 -O {$target} http://www.yzb.com/xuexi.mp4
其中 $target 是保存的路径, 后面 xuexi.mp4 是需要上传的文件, 这个命令要发在最终要上传到的机器上面执行
接下来讲下命令含义
1,wget 中
-c 重新启动下载中断的文件, 也就是断点续传
-t 链接到资源的超时时间, 我是设定如果两分钟内还找不到资源就超时
-O 将下载下来的文件重命名
那断点续传的问题解决了, 我们需要解决 PHP 代码的问题, 怎么说呢, 如果 B 机器是请求到 A 上的一个 PHP 脚本, 然后 PHP 脚本执行 wget 命令, 那么就会有一个超时的问题, 因为 A 在用 wget 下载 B 上的 xuexi.mp4 的时候, 一定会很久, 如果 PHP 脚本长时间无法回应 B 的请求的时候, 就会报 502 超时, 那这个怎么办呢
我们知道, 一个外部请求到 php, 需要经过 nginx 代理发送到 php-fpm 上, 然后 php-fpm 调用 PHP 解释器编译 PHP 代码
那这样的话, nginx 这一层就会超时, 那要怎么不超时, 异步上传呢
首先先写一个父脚本, 这个父脚本只有一件事, 直接调用 php-fpm 执行 PHP 上传脚本
父脚本核心代码
pclose(popen("/yzb/php/bin/php downloadFile.php 2>&1 &", "r"));
上面的代码可以快速结束, 而不像 exec 函数那样要等里面的命令执行完毕才能进行下一步, 就解决请求超时的问题. 大家可以看到, 命令的最后加了个 & 符号, 这个是告诉服务器, 这是一条需要后台执行的脚本, 通过 popen 来执行, 可以异步执行下载的脚本
downloadFile.php 核心代码
exec("wget -c -t 10 -T 120 -O {$target} http://www.yzb.com/demo.php 2>&1", $output, $return_val);
记得加上 2>&1, 这是告诉服务器这条命令的输出是要保存在变量里的, 这样 $output 才能获取到执行后的结果
这样 downloadFile.php 是直接通过 php-fpm 来执行, 执行完之后改下这个文件的上传状态即可, 这样就完成一个简单的异步断点续传的功能
来源: http://www.bubuko.com/infodetail-2679796.html