跟踪的下载进度在PHP

问题描述:

所有,跟踪的下载进度在PHP

我建立了一个表格,如果用户在填写表单,我的代码可以决定需要什么(大)文件由该用户下载。我使用下载按钮显示每个文件,并且我想显示该按钮旁边该文件的下载状态(正在下载,正在取消/中止或完成)。由于文件很大(200 MB +),我使用一个众所周知的功能来读取要在chunck中下载的文件。 我的想法是记录数据库中每个(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; 
    } 

奇怪的是,我的下载以恒定的速率运行顺利,但我的数据库获取尖峰更新:有时我看到一对夫妇数据库更新十几的(这样一对夫妇几十个千字节的块)在一秒钟之内,下一刻我看不到数据库更新(因此没有100 k个块由PHP提供)长达一分钟(这个超时取决于可用于下载的带宽)。事实上,没有进展是写一分钟,使我的代码相信下载被中止。在此期间,我看到IIS的内存使用量在不断增加,所以我得到了IIS缓冲PHP提供的大量数据的想法。 我的网络服务器在FastCGI模式下运行Windows 2008 R2数据中心(64位),IIS 7.5和PHP 5.3.8。有什么我可以做的(在我的代码中,在我的PHP配置中或在IIS配置中)防止IIS缓存PHP提供的数据,或者如果生成的数据实际传递到下载客户端? 在此先感谢!

+0

从PHP下载取得进展是不可能的:) – OptimusCrime 2012-04-13 09:37:49

+0

@OptimusCrime:错误。使用数据库写入状态,并使用Ajax读取它。也许使用APC。 – 2012-04-13 09:41:05

+0

@OptimusCrime - 它是如果你做什么操作系统正在做的事情,通过将文件分解成单独的部分,并记录每个部分交付 – BenOfTheNorth 2012-04-13 09:41:28

我问了一个similar question一次,并得到了非常好的结果与答案。

基本上,您使用APC缓存来缓存变量,然后使用来自客户端的Ajax调用在不同的页面中检索它。

另一种可能性是对数据库也这样做。将进度写入数据库,并让客户端使用Ajax调用来测试(假设每秒)。

由于没有有用的答案出现,我创建了一个真正的狡猾的解决方法,严格使用Apache来下载文件。整个表单,CSS等仍然通过IIS提供,只是下载链接由Apache服务器(反向代理服务器位于两者之间,因此用户无需摆弄端口号,代理服务器负责此操作)。 Apache不会缓存PHP输出,所以我在数据库中获得的时间戳是可靠的。