Apache / PHP专家?大文件下载失败:空文件以零KB保存

时间:2009-11-25 08:07:26

标签: php apache download

我有一个网页,用于为经过身份验证的用户提供下载文件的访问权限。这些文件位于根文件夹中(通常不是HTTP可访问的),我使用PHP脚本和fopen函数生成开始下载文件的网页。它适用于三个文件(所有文件都在200KB以下),但第四个文件 - 即40MB - 保存为空文件。

如果我将40MB文件移动到HTTP可访问文件夹,则该文件的链接可以正常工作,但它显然不能提供我想要的受限访问。

我已在脚本中确认PHP正在找到该文件,但出于某种原因,当发送标头时,40MB文件立即完成下载并且为0KB。

有趣的是,此代码在我的本地开发服务器上运行正常,但在生产服务器上运行不正常。两者都运行相同版本的PHP(5.2.10),并具有相同的内存和执行时间设置(32M和30secs)。我试着提高生产memory_limit和max_execution_time值(到64M和60secs)但它没有效果。

有什么想法吗?这是我的PHP脚本(文件名已更改为保护无知者):

<?php
// Download filename given in the $_GET['filename'] variable
$filepath = $_SERVER['DOCUMENT_ROOT'] . '/../';
if (isset($_REQUEST['type'])) {
 switch (strtoupper($_REQUEST['type'])) {
 case 'EVAL':
  $filename = "littlefile1.zip";
  break;
 case 'EXE':
  $filename = "bigfile.zip";
  break;
 case 'RPT':
  $filename = "littlefile2.zip";
  break;
 case 'UPD':
  $filename = "littlefile3.zip";
  break;
 default:
  die();
 }


 header("Content-Disposition: attachment; filename=" . $filename);
 header("Content-Length: " . filesize($filepath . $filename));
 header("Content-Type: application/octet-stream");
 $fp=fopen($filepath . $filename, 'rb');
 fpassthru($fp);
 ob_flush();
 fclose($fp);
}
?>

提前致谢!

在回应Greg的评论时,我得到的标题错误如下:

Date: Sun, 29 Nov 2009 19:58:16 GMT
Server: Apache/2.2.3 (Red Hat)
X-Powered-By: PHP/5.2.10
Content-Disposition: attachment; filename=bigfile.zip
Content-Encoding: gzip
Vary: Accept-Encoding
Content-Length: 44964864
Connection: close
Content-Type: application/octet-stream

500 Internal Server Error

4 个答案:

答案 0 :(得分:0)

如果你设置error_reporting(E_ALL);,你会收到任何错误吗?

我看到的唯一的事情是脚本时间限制和一些内存问题但是因为你说你已经检查了两者。

答案 1 :(得分:0)

您是否使用输出缓冲(使用ob_start())?如果没有,则必须使用flush()而不是ob_flush(),并且必须在发送文件之前调用它。通过安全,您可以调用ob_clean()来清除输出缓冲区。顺便说一句,readfile()使您不必使用fopen(),fpassthru()和fclose()。

<?php
// Download filename given in the $_GET['filename'] variable
$filepath = $_SERVER['DOCUMENT_ROOT'] . '/../';
filenames['EVAL'] = "littlefile1.zip";
filenames['EXE'] = "bigfile.zip";
filenames['RPT'] = "littlefile2.zip";
filenames['UPD'] = "littlefile3.zip";
if (isset($_REQUEST['type'])) {
 $filename = filenames[strtoupper($_REQUEST['type'])];
 if (!empty($filename) && file_exists( $filepath . $filename)) {
   header("Content-Disposition: attachment; filename=" . $filename);
   header("Content-Length: " . filesize($filepath . $filename));
   header("Content-Type: application/octet-stream");
   flush();
   ob_clean();
   readfile($filepath . $filename);
 }
 exit;
}

答案 2 :(得分:0)

我敢打赌,啤酒提供商将error_reporting设置为0,或者错误重定向到日志文件,因此会出现一些错误,但不会报告。

  • 您可以输出$ _REQUEST [“type”]的测试输出吗?可能是你的switch语句中是否为空?

  • 您是否可以故意插入会导致致命错误的内容,并查看是否留空?

  • 正如RageZ建议的那样,你可以将error_reporting设置为E_ALL吗?

  • 默认情况下,错误不会显示在输出中,而是重定向到内部错误日志文件。您能否与您的提供商核实是否属实?也许您有一个登录区域来查看错误日志,或者它们存储在目录结构中的某个位置?

答案 3 :(得分:0)

内容 - 处置:附件;文件名= Jobchart.msi

该文件确实存在吗?