我想知道是否有办法知道文件是否已完全下载。即,下载文件后是否可以触发某些操作(例如向服务器发送消息或提醒用户等)。
可能在java、php中。
谢谢你。
尽管有相反的评论,但这是可能的,尽管它不适合胆小的人,因为它需要一些 HTTP 协议知识以及对文件流的理解。
假设 PHP ...
ignore_user_abort()
——这将允许 php 脚本在用户关闭连接后继续运行Connection: close
标头和一个Content-Length: 1234
标头,其中 1234 是所服务文件的大小。fwrite
,跟踪您输出的字节数。一旦输出字节数达到文件大小,你就知道你已经完成了。客户端将关闭连接,但您的脚本将继续运行。不过要小心,因为在 Web SAPI 中,您很容易遇到 PHP 的最大时间限制。
更新:
值得一提的是,如果您这样做,您还应该connection_aborted
在输出循环中添加一个检查,这样如果客户端在完成传输之前中止连接,您就不会继续流式输出。这应该是常识,但不要说我没有警告过你。
只需通过 phpscript 发送文件.. 例如http://exmaple.com/download.php?filename=some_filename.txt
$file=$_GET['filename'];
if (file_exist($file)){
send_message_to_somebody(); //DO what ever you want here and then
$mime = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $file);
header("Content-Type: " . $mime);
header("Content-Transfer-Encoding: binary");
header('Accept-Ranges: bytes');
header('Content-Disposition: attachment; filename="' . basename($file).'"');
header('Content-Length: ' . filesize($file));
readfile($file);
}
将信息写入数据库,如果下载被取消/中止,“is_downloaded”之类的列将为0,而不是1...描述不佳,没有时间。
这里重要的是_destruct(),它是下载完成的触发器。
<?php
class Download
{
protected $file;
private $session;
private $_last_insert_id;
public function __construct($file, $session)
{
$this->file = $file;
$this->session = $session;
}
public function send()
{
$info = pathinfo($this->file);
$query = DB::insert('downloads', array('user_id', 'file', 'path', 'start'))
->values(array($this->session->get('id'), $info['basename'], $this->file, DB::expr('NOW()')))
->execute();
$this->_last_insert_id = $query[0];
$this->session->set('downloading', 1);
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$info['basename'].'"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($this->file));
readfile($this->file);
}
public function __destruct()
{
$aborted = connection_aborted();
$this->session->set('downloading', 0);
$query = DB::update('downloads')->set(array('stop' => DB::expr('NOW()')))->where('id', '=', $this->_last_insert_id)->execute();
}
}