2012-04-13 7 views
1

すべてには、私は、ユーザーがフォームに入力すれば、私のコードは、(大)ファイルは、そのユーザがダウンロードする必要があるかを判断することができ、フォームを構築している、PHP

をダウンロードの進行状況を追跡します。私は各ファイルをダウンロードボタンで表示し、ボタンの隣にそのファイルのダウンロードのステータス(ダウンロードの進行中、キャンセル/中止または完了)を表示したいとします。ファイルは大きいので(200 MB +)、よく知られている関数を使ってファイルを読み込んでchuncksにダウンロードします。 私のアイデアは、データベースの各(100キロバイト)チャンクの読み込みを記録することで、ダウンロードの進行状況を追跡することができました。 私のコードは以下の通りです:時々私は、データベースの更新のダースのカップルを参照してください(のようにカップル:

function readfile_chunked($filename, $retbytes = TRUE) 
    { 
      // Read the personID from the cookie 
      $PersonID=$_COOKIE['PERSONID']; 
      // Setup connection to database for logging download progress per file 
      include "config.php"; 
      $SqlConnectionInfo= array ("UID"=>$SqlServerUser,"PWD"=>$SqlServerPass,"Database"=>$SqlServerDatabase); 
      $SqlConnection= sqlsrv_connect($SqlServer,$SqlConnectionInfo); 
      ChunckSize=100*1024; // 100 kbyte buffer 
      $buffer = ''; 
      $cnt =0; 
      $handle = fopen($filename, 'rb'); 
      if ($handle === false) 
      { 
       return false; 
      } 
      $BytesProcessed=0; 
      while (!feof($handle)) 
      { 
       $buffer = fread($handle, $ChunckSize); 
       $BytesSent = $BytesSent + $ChunckSize; 
       // update database 
       $Query= "UPDATE [SoftwareDownload].[dbo].[DownloadProgress] SET  LastTimeStamp = '" . time() . "' WHERE PersonID='$PersonID' AND FileName='$filename'"; 
       $QueryResult = sqlsrv_query($SqlConnection, $Query); 
       echo $buffer; 
       ob_flush(); 
       flush(); 
       if ($retbytes) 
       { 
         $cnt += strlen($buffer); 
       } 
      } 
      $status = fclose($handle); 
      if ($retbytes && $status) 
      { 
       return $cnt; // return num. bytes delivered like readfile() does. 
      } 
      return $status; 
    } 

奇妙なことは、私のダウンロードは一定の速度でスムーズに動作しますが、私のデータベースはスパイクに更新されるということです(100KBのブロックがPHPによって供給されることはありません)を1分(このタイムアウトはダウンロードに使用可能な帯域幅によって決まります)表示していません。何の進展もなく、ダウンロードが中止されたと私のコードは考えています。 その間、私はIISのメモリ使用量が増えていることを知っています。そのため、IISがPHPが提供するデータのチャンクをバッファリングするという考えが得られます。 私のWebサーバは、FastCGIモードでWindows 2008 R2データセンター(64ビット)、IIS 7.5およびPHP 5.3.8を実行しています。 IISがPHPの提供するデータをキャッシュするのを防ぐために、自分のコード(PHPの設定やIISの設定で)で行うことができますか?また、生成されたデータが実際にPHPに渡されるかどうかはPHPで確認できます。クライアントをダウンロードしていますか? ありがとうございます!

+0

PHPでダウンロードして進歩させることはできません:) – OptimusCrime

+0

@OptimusCrime:間違っています。データベースを使用してステータスを書き、Ajaxで読み込みます。おそらくAPCを使用します。 –

+0

@OptimusCrime - OPが何をしているのか、ファイルを別々の部分に分割し、各部分が配信されるときにログすることで、それは – BenOfTheNorth

答えて

0

私はsimilar questionを一度尋ねてきましたが、その回答が非常に良好です。

基本的に、APCキャッシュを使用して変数をキャッシュし、クライアントからのAjaxコールを使用して別のページでその値を取得します。

もう1つの可能性は、データベースで同じことを行うことです。進捗状況をデータベースに書き込んで、クライアントにAjax呼び出しを使ってそれをテストさせるようにしましょう(毎秒)。

1

有用な答えが出てこなかったので、私はファイルをダウンロードするためにApacheを厳密に使用することで、実際の厄介な回避策を作成しました。フォーム全体、CSSなどはIIS経由で配信されますが、ダウンロードリンクはApacheのサーバーです(リバースプロキシサーバーがその間に置かれているため、ユーザーはポート番号を知っている必要はありません。 ApacheはPHP出力をキャッシュしないため、データベースに取得するタイムスタンプは信頼できます。

関連する問題