php 能否检测用户是否已开始下载

yktd26 2013-01-22 11:47:00
有个项目提供文件下载,因为需要检测用户是否完成了下载,有下面一段代码

...
ignore_user_abort(true);
if ($fd = fopen($filePath, 'rb')) {
session_write_close();
if ($start_offset > 0)
fseek($fd, $start_offset);
while (!feof($fd)) {
print (fread($fd, 16384));
}

fclose($fd);
}
if (connection_aborted()){
...
}
else {
...
}
...


现在出现了一个问题是,如果是大文件,没什么事,如果是小文件,当用户看到选择存储目录对话框稍等一会然后点cancel时,服务器端已将文件全部发送了,所以在做if (connection_aborted())时是false
想问问有没有什么方法,在比如说第一个print后发现用户还没有开始下载则暂停print,或者有没有办法禁止诸如buffering之类的以使在用户没有接受是block这个print,也就是print不能返回?

不知道解释的清不清楚
...全文
353 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
ImN1 2013-01-26
  • 打赏
  • 举报
回复
引用 13 楼 laoding_210 的回复:
python可以吧
底层协议的问题,跟语言无关,如果双方有约定,php也可以的
laoding_210 2013-01-26
  • 打赏
  • 举报
回复
python可以吧
yktd26 2013-01-25
  • 打赏
  • 举报
回复
引用 8 楼 xuzuning 的回复:
把 if (connection_aborted()){... 放一个在循环内
版主,还有别的idea么?
ImN1 2013-01-24
  • 打赏
  • 举报
回复
是否下载完成只能在客户端检测,如果你的项目不能控制客户端就无法检测 如果服务器端和客户端都能控制的话,可以在客户端接收完整后返回一个信息给服务器端 服务器端通过这个信息才能确定 例如你提到的 Transfer-Encoding:chunked,最后必定是\r\n0\r\n\r\n结束的 客户端收到这7个字节时返回一个约定的信息给服务器端,服务器端接收到就确定完成 如果服务器端没有接收到返回的信息,只能从超时或者捕捉连接异常确认客户端未完成 建议用socket和keep-alive去做这事 如果客户端不能控制,例如只是浏览器访问,是没有返回信息的 但下载中途按cancel应该会发送一个关闭连接的信息给服务器端,socket能捕捉这个关闭的 可以检测一下socket.send()发送了多少字节 不过这样很不靠谱,正如你说的小文件可能已经全部发送了,但客户端只是收进缓存,cancel只是没做写文件或类似move的操作 例如csdn的资源下载,好几M大的文件,我通常都是“秒杀”,选好文件名按OK就立即传完了,都不知道csdn怎么做到的……
LuciferStar 2013-01-24
  • 打赏
  • 举报
回复
服务器发送header,紧接着是文件数据 浏览器接收header后,会立即接收后续的数据。在浏览器解析header的同时,下载已经开始了,只不过下载到缓存里的。
LuciferStar 2013-01-23
  • 打赏
  • 举报
回复
PHP没法知道。
Colombian 2013-01-23
  • 打赏
  • 举报
回复
一般来说,我们可以通过直接让URL指向一个位于Document Root下面的文件,来引导用户下载文件。但是, 这样做,就没办法做一些统计, 权限检查, 等等的工作。于是,很多时候,我们采用让PHP来做转发,为用户提供文件下载。
 $file = "/tmp/dummy.tar.gz";

 header("Content-type: application/octet-stream");

 header('Content-Disposition: attachment; filename="' . basename($file) . '"');

 header("Content-Length: ". filesize($file));

 readfile($file);
yktd26 2013-01-23
  • 打赏
  • 举报
回复
引用 8 楼 xuzuning 的回复:
把 if (connection_aborted()){... 放一个在循环内
谢谢版主,等你等的好幸苦,试了你的方法,甚至加上了'Transfer-Encoding:chunked',还是不管用,因为我看到其实在用户选择ok或者cancel之前浏览器已经开始下载了,所以如果是小文件就有几率在他选择之前文件已经下载结束,而connection并没有aborted还有没有其他建议可以我试试??不知道http协议里有没有什么特别隐蔽的header可以禁止用户提前下载啊,我在科幻世界了呵呵

header('Transfer-Encoding:chunked');
ob_flush();
flush();
...
while (!feof($fd)) {
	if (connection_aborted()){
		fclose($fd);
		break;
	}
	$data = fread($fd, 16384);
	if (strlen($data)){
		echo dechex(strlen($data)), "\r\n", $data, "\r\n";
	}
	
	ob_flush();
	flush();	
}
xuzuning 2013-01-23
  • 打赏
  • 举报
回复
把 if (connection_aborted()){... 放一个在循环内
林_ 2013-01-23
  • 打赏
  • 举报
回复
引用 6 楼 ma_lin_1 的回复:
引用 4 楼 craboy1 的回复: PHP服务端脚本,那是浏览器的行为了,php是有心无力。 不知道哇哦
不知道哇哦
林_ 2013-01-23
  • 打赏
  • 举报
回复
引用 4 楼 craboy1 的回复:
PHP服务端脚本,那是浏览器的行为了,php是有心无力。
不知道哇哦
yktd26 2013-01-23
  • 打赏
  • 举报
回复
引用 3 楼 LuciferStar 的回复:
PHP没法知道。
那有没有可能通过某种办法和前端js配合来实现在用户真正确认目标文件夹前限制下载?
craboy1 2013-01-23
  • 打赏
  • 举报
回复
PHP服务端脚本,那是浏览器的行为了,php是有心无力。

20,360

社区成员

发帖
与我相关
我的任务
社区描述
“超文本预处理器”,是在服务器端执行的脚本语言,尤其适用于Web开发并可嵌入HTML中。PHP语法利用了C、Java和Perl,该语言的主要目标是允许web开发人员快速编写动态网页。
phpphpstorm 技术论坛(原bbs)
社区管理员
  • 开源资源社区
  • phpstory
  • xuzuning
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧