下载问题:缓慢和/或失败

时间:2010-02-18 09:40:34

标签: php apache download halt

我有以下脚本让访问者下载文件:

header( 'Content-Type: application/octet-stream' );
header( 'Content-Transfer-Encoding: binary' );
header( 'Content-Disposition: attachment; filename=' . $fileName );
header( 'Content-Length: ' . filesize( $filePath ) );
header( 'Content-Description: Download' );
header( 'Cache-Control: private' );
header( 'Pragma: no-cache' );
header( 'Expires: 0' );

readfile( $filePath );
exit();

效果不佳。 (我也把文件名放在引号中,结果相同)。

它表现得非常慢,有时下载甚至会停止。特别是在Opera中,它停止了99%的下载。有时它甚至会立即显示99%完成,然后开始下载并停止在34%左右。

服务器是共享主机,Mac OS X服务器。

使用Firefox的Live HTTP标头附加组件,我注意到服务器在响应中添加了附加标头:

HTTP/1.1 200 OK
Date: Thu, 18 Feb 2010 09:27:25 GMT
Server: Apache
X-Powered-By: PHP/5.2.12
Content-Transfer-Encoding: binary
Content-Disposition: attachment; filename=test.psd
Content-Length: 398635
Content-Description: Download
Cache-Control: private
Pragma: no-cache
Expires: 0
Content-Encoding: gzip // <-- expecially this one,
Vary: Accept-Encoding // <-- this one,
MS-Author-Via: DAV // <-- and this one
Keep-Alive: timeout=10, max=100
Connection: Keep-Alive
Content-Type: application/octet-stream

这些可能是问题的原因吗?

当我在本地主机上运行脚本时,一切正常。此外,当我直接从该主机下载文件时,速度也很好而且流畅。

我对这一点真的很无能为力。你的帮助是预先确定的。提前谢谢。

更新

我认为我已将问题缩小到瓶颈。 Web服务器自动gzip压缩输出。当我从PHP脚本中删除Content-Length标题时,一切都开始顺利下载。这是有道理的:Content-Length的值不再与实际的gzip压缩输出相匹配。在PHP中,我读取了未压缩的文件大小来设置Content-Length标头,但之后,Apache会对其进行压缩,这可能是浏览器被阻塞的地方。

我将按照这个问题提出一个问题,即当网络服务器自动gzip压缩输出时如何设置正确的Content-Length标题大小。

3 个答案:

答案 0 :(得分:0)

尝试取消设置gzip-Content-Encoding。

在脚本的最开头使用ob_start();在设置标题之前,请使用@ob_end_clean();并在其之后,明确设置header("Content-Encoding:");以尝试取消设置可能出现的任何gzip-Encoding。 在文件末尾@ob_end_flush();

输出缓冲功能非常方便使标头设置更加安全,但可能与您的问题无关。我只记得在一个设置中遇到问题,其中封闭的PHP代码使用ob_gzhandler并且我需要取消它。

答案 1 :(得分:0)

我使用下面的代码,它的工作原理。告诉你真相我没有说明我所发送的所有标题,我仍然没有时间去调查,我找到了解释:

来源:

http://www.opendesigns.org/forum/discussion/1437/php-download-counter/#pgbottom http://www.webdeveloper.com/forum/showthread.php?t=115815&highlight=PHP+download+counter http://php.net/manual/en/function.header.php#83384

无论如何它起作用:

   /*
   TODO: still to be read and better understood.
   */

   //no caching (I don't uderstand what is this part useful for)
   header("Pragma: public"); //?
   header("Expires: 0"); //?
   header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); //?
   header("Cache-Control: private", false); //?

   //sending download file
   header("Content-Type: application/octet-stream"); //application/zip can use application/octet-stream that is more generic it works because in now days browsers are able to detect file anyway
   header("Content-Disposition: attachment; filename=\"" . basename($file_serverfullpath) . "\""); //ok
   header("Content-Transfer-Encoding: binary"); //?
   header("Content-Length: " . filesize($file_serverfullpath)); //ok
   readfile($file_serverfullpath);

答案 2 :(得分:0)

我已将问题缩小到瓶颈。 Web服务器自动gzip压缩输出。当我从PHP脚本中删除Content-Length标头时,一切都开始顺利下载。这是有道理的:Content-Length的值不再与实际的gzip压缩输出相匹配。在PHP中,我读取了未压缩的文件大小来设置Content-Length标头,但之后,Apache压缩它,这可能是浏览器被阻塞的地方。