【问题标题】:Keep track of download progress in PHP在 PHP 中跟踪下载进度
【发布时间】:2012-04-13 09:33:33
【问题描述】:

全部,

我已经建立了一个表格,如果用户填写表格,我的代码可以确定该用户需要下载哪些(大)文件。我用下载按钮显示每个文件,我想在按钮旁边显示该文件的下载状态(下载正在进行、取消/中止或完成)。因为文件很大(200 MB+),所以我使用一个众所周知的函数来读取要以块下载的文件。 我的想法是记录数据库中每个(100 KB)块的读取,这样我就可以跟踪下载进度。 我的代码如下:

    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 KB 块),下一刻,我看到没有数据库更新(因此 PHP 没有提供 100 k 块)长达一分钟(此超时取决于可用于下载的带宽)。一分钟内没有写入任何进度的事实使我的代码认为下载已中止。 与此同时,我看到 IIS 的内存使用量在增加,因此我认为 IIS 会缓冲 PHP 提供的数据块。 我的网络服务器在 FastCGI 模式下运行 Windows 2008 R2 数据中心(64 位)、IIS 7.5 和 PHP 5.3.8。我可以做些什么(在我的代码、我的 PHP 配置或 IIS 配置中)以防止 IIS 缓存 PHP 提供的数据,或者如果生成的数据实际传递到下载客户端? 提前致谢!

【问题讨论】:

  • 无法通过 PHP 获取下载进度 :)
  • @OptimusCrime:错了。使用数据库写入状态,并使用 Ajax 读取。也许使用 APC。
  • @OptimusCrime - 如果你按照 OP 正在做的事情,将文件分成单独的部分,并在每个部分交付时记录
  • 谢谢大家,但 Ben 所说的正是我的问题所在:我将文件分成几部分,并在交付部分时写入数据库。但是,由于 IIS 介于两者之间,PHP 将文件部分传递给 IIS 而不是客户端。我想知道如何绕过 IIS 缓存,所以我的部分以更流畅的方式交付(而不是“让我们在缓冲区中推送 100 兆字节并等待一分钟) -for-it-to-clear”的方式,就像现在正在发生的那样)。

标签: php iis download progress


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    我曾经问过一次similar question,得到了很好的答案。

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

    另一种可能性是对数据库执行相同的操作。将进度写入数据库并让客户端使用 Ajax 调用对其进行测试(假设每秒)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多