0

我想知道是否有办法知道文件是否已完全下载。即,下载文件后是否可以触发某些操作(例如向服务器发送消息或提醒用户等)。

可能在java、php中。

谢谢你。

4

3 回答 3

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 的最大时间限制。


更新:

值得一提的是,如果您这样做,您还应该connection_aborted在输出循环中添加一个检查,这样如果客户端在完成传输之前中止连接,您就不会继续流式输出。这应该是常识,但不要说我没有警告过你。

于 2012-08-09T16:58:27.253 回答
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);
}
于 2012-08-09T16:59:12.307 回答
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();
  }

}
于 2012-08-09T17:06:32.270 回答