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」のような列は 1 ではなく 0 になります... 説明が不十分で、時間がありません。

ここで重要なのは、ダウンロード完了のトリガーとなる_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 に答える