Problem with downloads: slow and/or fails

随声附和 提交于 2019-12-12 01:34:35

问题


I have the following script to let a visitor download a file:

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();

It doesn't work very well. (I've also put the filename in quotes, same result).

It behaves very slow, and sometimes the downloads even halt. In Opera especially, it halts on 99% of the download. Sometimes it even immediately shows 99% completed, then it starts downloading and halts at around 34%.

The server is a shared host, Mac OS X server.

With using Firefox's Live HTTP headers add-on, I've noticed the server adds aditional headers to the response:

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

Could these be the cause of the problem?

When I run the script on my localhost everything works fine. Also, when I directly download files from this host, the speed is also fine and fluent.

I'm really rather clueless on this one. Your help is appeciated. Thank you in advance.

UPDATE:

I think I have narrowed the problem down to the bottleneck. The webserver automatically gzip compresses the output. When I removed the Content-Length header from my PHP script everything started downloading smooth. This makes sense: The value of the Content-Length doesn't match the actual gzipped output anymore. In PHP I read the uncompressed filesize to set the Content-Length header, but afterwards, Apache compresses it, and this is probably where the browsers choked.

I'll follow this question up with a question about how to set the correct Content-Length header size when the webserver automatically gzip compresses output.


回答1:


Try unsetting the gzip-Content-Encoding.

Use ob_start() at the very beginning of your script; before setting your headers, use @ob_end_clean(); and right after it, explicitely set header("Content-Encoding:"); to try to unset any gzip-Encoding that might come in. At the end of your file place @ob_end_flush();.

The output buffering functions are handy to make the header-setting more failsafe, but probably not related to your problem. I just remember to ran into problems in a setup where the enclosing PHP code used ob_gzhandler and I needed to unset it.




回答2:


I use the code below and it works. Telling you the truth I did not undersyand yet properly all the header that I send, I still did not have the time to investigate, I found explanations in:

Sources:

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

anyway it works:

   /*
   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);



回答3:


I have narrowed the problem down to the bottleneck. The webserver automatically gzip compresses the output. When I removed the Content-Length header from my PHP script everything started downloading smooth. This makes sense: The value of the Content-Length doesn't match the actual gzipped output anymore. In PHP I read the uncompressed filesize to set the Content-Length header, but afterwards, Apache compresses it, and this is probably where the browsers choked.



来源:https://stackoverflow.com/questions/2287576/problem-with-downloads-slow-and-or-fails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!