2012-08-09 81 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(); 
    } 

} 
相關問題