我有一个简单的文件上传服务,用PHP编写,其中还包括一个脚本,当用户请求从该站点下载时,通过发送有限大小的数据包来控制下载速度。
如果不是高级会员,我想实施一个系统,将并行/同步下载限制为每用户1个。在上面的下载脚本中,我可以使用MySQL数据库来存储具有以下内容的记录:(1)用户ID; (2)文件ID; (3)下载开始时; (4)当最后一个数据包被发送时,每次完成时更新(如果DL速度限制在150 kB / sec,那么在每150 kB之后,此记录将被更新,等等。)
但是,到目前为止,只有在下载成功完成后才会删除数据库记录 - 在脚本结束时,在完全下载完成后,记录将从表中删除:
insert DB record;
while (download is being served) {
serve packet of data;
update DB record with current date/time;
}
// Download is now complete
delete DB record;
我如何能够检测下载何时被取消?如果现有的下载记录超过X分钟/小时,我是否只需要有一个Cron作业(或类似的东西)检测?或者我还有别的东西可以让我失踪吗?
我希望我已经解释得这么好了。我认为不需要发布特定代码;我对如何/是否可以这样做的后勤工作更感兴趣。如果需要具体,我很乐意提供。
注意:我知道如何检测文件是否已成功下载;我需要知道如何检测它是否被取消,中止或以其他方式停止(而不仅仅是暂停)。 这将有助于停止并行下载,以及防止用户取消下载#1并尝试启动下载#2的情况,只是发现该网站声称他仍在下载文件#1。
编辑:你可以在这里找到我的下载脚本:http://codetidy.com/1319/ - 它已经支持多部分下载和下载恢复。
答案 0 :(得分:4)
<?php
class DownloadObserver
{
protected $file;
public function __construct($file) {
$this->file = $file;
}
public function send() {
// -> note in DB you've started
readfile($this->file);
}
public function __destruct() {
// download is done, either completed or aborted
$aborted = connection_aborted();
// -> note in DB
}
}
$dl = new DownloadObserver("/tmp/whatever");
$dl->send();
应该工作得很好。无需shutdown_function或任何时髦的自建连接观察。
答案 1 :(得分:1)
您需要查看以下函数:connection_status(),connection_aborted()和ignore_user_abort()(有关详细信息,请参阅PHP手册的connection handling部分)。
虽然我无法保证可靠性(自从我玩过它以来已经有一段时间了),但如果正确的组合,你应该能够完成你想要的。但是在处理这些问题时有一些注意事项,最重要的一点是,如果出现问题,您最终可能会在服务器上运行搁浅的PHP脚本,要求您杀死Apache以阻止它们。
以下内容应该让您对如何操作有所了解(改编自PHP代码示例和一些注释):
<?php
//Set PHP not to cancel execution if the connection is aborted
//and drop the time limit to allow for big file downloads
ignore_user_abort(true);
set_time_limit(0);
while(true){
//See the ignore_user_abort() docs re having to send data
echo chr(0);
//Make sure the data gets flushed properly or the connection check won't work
flush();
ob_flush();
//Check then connection status and exit loop if aborted
if(connection_status() != CONNECTION_NORMAL || connection_aborted()) break;
//Just to provide some spacing in this example
sleep(1);
}
file_put_contents("abort.txt", "aborted\n", FILE_APPEND);
//Never hurts to ensure that the script halts execution
die();
显然,对于你将如何使用它,发送的数据只是下载数据块(只需确保正确刷新缓冲区以确保实际发送数据)。据我所知,没有办法区分暂停和中止/停止。暂停/恢复功能(以及多部分下载 - 即下载管理器如何加速下载)依赖于“范围”标题,基本上请求文件的字节x到字节y。因此,如果你想允许可恢复的下载,你也必须处理它。
答案 2 :(得分:0)
默认情况下,没有HTTP“取消”信号。因此,看起来您需要决定超时,连接可以在不发送/接收另一个数据包的情况下持续的时间长度。如果您要发送相当小的数据包(我认为您是这样),请将超时保持为最佳效果。
在你的状态下你需要检查上次时间戳更新的年龄,如果它太旧,就停止发送文件。