如何判断一个文件被客户端成功下载
rt,如何能够确认文件被客户端成功下载?
[解决办法]
一般情况下当输出完头以后就直接将整个文件输出出去
通常用的是 ceho、print 有的干脆用 readfile
这样 php 就没有机会去判断用户是否终止了下载
你需要在循环中用较小的块,通过 sprintf 输出文件内容
springf 函数会返回一个表示输出了多少字符的数。你可以累计这个数,并与文件长度进行比较
从而判断下载是否完成
[解决办法]
基本上是没法判断的。。。
[解决办法]
基于http是没办法做到的。比如服务器返回了2000个字节让你下载保存,这时候你在你在浏览器点了取消按钮,或者下载到一半取消,再或者下载完成,这些个动作只在客户端浏览器执行,并不会将状态通知服务器。
[解决办法]
说的不对,应该说基于浏览器的客户端无法做到,下载保存那些动作是浏览器帮你处理的。
如果说你自己写个客户端,很容易可以判断,计算返回字节数,统计保存成文件的字节数两个一比较就行。
[解决办法]
IE下可使用ActiveX,FireFox下可以使用NPAPI
[解决办法]
一般来讲,要判断文件下载完毕的话需要通过控件来实现。普通的JS是没法判断的。
[解决办法]
send_file('03.bmp',1);//为了测试方便我取了较小的块尺寸
function send_file($file, $speed = 100) {
//First, see if the file exists
if (!is_file($file)) {
die("<b>404 File not found!</b>");
}
//Gather relevent info about file
$filename = basename($file);
$file_extension = strtolower(substr(strrchr($filename,"."),1));
// This will set the Content-Type to the appropriate setting for the file
switch( $file_extension ) {
case "exe":
$ctype="application/octet-stream";
break;
case "zip":
$ctype="application/zip";
break;
case "mp3":
$ctype="audio/mpeg";
break;
case "mpg":
$ctype="video/mpeg";
break;
case "avi":
$ctype="video/x-msvideo";
break;
// The following are for extensions that shouldn't be downloaded
// (sensitive stuff, like php files)
case "php":
case "htm":
case "html":
case "txt":
die("<b>Cannot be used for ". $file_extension ." files!</b>");
break;
default:
$ctype="application/force-download";
}
// Begin writing headers
header("Cache-Control:");
header("Cache-Control: public");
header("Content-Type: $ctype");
$filespaces = str_replace("_", " ", $filename);
// if your filename contains underscores, replace them with spaces
$header='Content-Disposition: attachment; filename='.$filespaces;
header($header);
header("Accept-Ranges: bytes");
$size = filesize($file);
// check if http_range is sent by browser (or download manager)
if(isset($_SERVER['HTTP_RANGE'])) {
// if yes, download missing part
$seek_range = substr($_SERVER['HTTP_RANGE'] , 6);
$range = explode( '-', $seek_range);
if($range[0] > 0) { $seek_start = intval($range[0]); }
if($range[1] > 0) { $seek_end = intval($range[1]); }
header("HTTP/1.1 206 Partial Content");
header("Content-Length: " . ($seek_end - $seek_start + 1));
header("Content-Range: bytes $seek_start-$seek_end/$size");
} else {
header("Content-Range: bytes 0-$seek_end/$size");
header("Content-Length: $size");
}
//open the file
$fp = fopen("$file","rb");
//seek to start of missing part
fseek($fp,$seek_start);
/*** 到此为止都是普通的写法 ***/
//start buffered download
$n = 0; //输出长度计数器复位
//reset time limit for big files
set_time_limit(0);
while(!feof($fp)) {
$n += printf('%s', fread($fp,1024*$speed)); //输出内容并累计输出长度
file_put_contents('file_down_info.txt', sprintf('size:%d len:%d', $size, $n));//因为是测试所以每步都保存了信息。实用时只需在循环后处理
flush();
sleep(1);
}
fclose($fp);
exit;
}