0

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

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

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

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

我真的对这个一无所知。你的帮助很受欢迎。先感谢您。

更新:

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

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

4

3 回答 3

0

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

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

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

于 2010-02-18T09:52:46.430 回答
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);
于 2010-02-18T10:11:28.573 回答
0

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

于 2010-02-23T08:51:18.813 回答