2012-08-09 73 views
0

我想知道是否有办法知道文件是否已完全下载。 即,一旦文件已被下载,是否可能触发某个动作(如向服务器发送消息或者提醒d用户等)。代码知道文件是否已被下载

可能在java,php。

谢谢。

+0

@Matt错了...... – rdlowrey 2012-08-09 16:51:30

+1

@rdlowrey我急着等待下面的答案,先生! – Matt 2012-08-09 16:55:30

+0

你的情况如何?你是否从网络服务器下载文件?这是什么类型的网络服务器?等一些更多的信息请 – Kostronor 2012-08-09 16:56:46

回答

3

尽管有相反的意见,但这个可能是,尽管它不适合心脏不好,因为它需要一些关于HTTP协议的知识以及对文件流的了解。

假设PHP ...

  1. 通过运行一个PHP脚本文件下载 - 即不具有Web服务器直接从磁盘提供服务的文件,有一个PHP脚本返回。
  2. 告诉PHP脚本ignore_user_abort() - 这将让PHP脚本继续在用户关闭连接后运行
  3. 发送Connection: close一个Content-Length: 1234头,其中1234是被服务的文件大小。
  4. 使用fwrite将文件流式传输到客户端,跟踪您输出的字节数。一旦输出字节数达到文件大小,就知道你已经完成了。客户端将关闭连接,但脚本将继续运行。
  5. 做任何事情你想通知自己或数据库或文本日志文件,下载成功完成。

但要小心,因为在一个web SAPI中,您可以轻松地运行在PHP的最大时间限制内。


UPDATE:

值得一提的是,如果你这样做,你也应该在你的输出循环增加一个检查connection_aborted,这样你就无法继续,如果流输出客户端在完成传输之前中止连接。这应该是常识,但不要说我没有提醒你。

+0

哇!这太棒了。我总是很高兴被证明是错误的,因为我每次都能学到新的东西! +1! – Matt 2012-08-09 17:13:41

+0

@Matt如果我有一个美元,每次有人证明我在这个网站上我错了,我会是一个有钱人:) – rdlowrey 2012-08-09 17:14:31

0

只需通过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); 
} 
+0

这将无法正常工作,因为有了上面的代码,php将尽快终止客户端关闭连接。服务器将无法知道文件是否实际完全下载。 – rdlowrey 2012-08-09 17:00:57

+0

你是对的,我没有仔细阅读 - 错过了_complete_下载很重要 – 2012-08-09 17:10:39

0

写信息,如果取消下载/中止,如“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(); 
    } 

} 
相关问题