Hello, we just moved to a new server using Debian6 and basically following "The Perfect Server" Howto. Everything is running smooth, except for one problem: when a client with small bandwidth tries to download a large zip file (120MB) from a login area of our main website, the download stops after a a few minutes and the result is a broken zip file with 6 to 40 MB - depending on the speed of their connection. I have yet to check logs, but Google tells me that this might be a problem with TCP/IP disconnecting after 5 Minutes of inactivity. I was able to reproduce the error from a slow connection. Will have to do further testing, but if someone here has encountered this before, please point me in the right direction... The script itself is about 1 yr old has not caused this behavior on the old webserver. - Richard
So far I tested only on FF4 on a MAC. I did look at Apache logs, these show the file being called and a status 200, but nothing in Error Logs. Since I have only approximate times from a salesperson that talked to the persons downloading the file, I have only found one entry that is fairly certain one that failed (since there are no other downloads for hours):
So the download is done with a php script? Which php method do you use in that website? It might be that a php or fcgi timeout causes the interruption.
I didn't write the script - it is a Download manager for Joomla that we modified quite a bit, but it seems it is using fopen(). Here comes the script, at least part of it: PHP: function download($inline = false) { // Fix [3164] while (@ob_end_clean()); if( $this->_isLink ){ header( "Location: " . substr( $this->name , 6 ) ); return; } $fsize = @filesize($this->path.$this->name); $mod_date = date('r', filemtime( $this->path.$this->name ) ); $cont_dis = $inline ? 'inline' : 'attachment'; // required for IE, otherwise Content-disposition is ignored if(ini_get('zlib.output_compression')) { ini_set('zlib.output_compression', 'Off'); } // fix for IE7/8, ticket #183 if(function_exists('apache_setenv')) { apache_setenv('no-gzip', '1'); } header("Pragma: public"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Expires: 0"); header("Content-Transfer-Encoding: binary"); header('Content-Disposition:' . $cont_dis .';' . ' filename="' . str_replace('"', '\"', $this->name) . '";' . ' modification-date="' . $mod_date . '";' . ' size=' . $fsize .';' ); //RFC2183 header("Content-Type: " . $this->mime ); // MIME type header("Content-Length: " . $fsize); if( ! ini_get('safe_mode') ) { // set_time_limit doesn't work in safe mode @set_time_limit(0); } // No encoding - we aren't using compression... (RFC1945) //header("Content-Encoding: none"); //header("Vary: none"); $this->readfile_chunked($this->path.$this->name); // The caller MUST 'die();' } function readfile_chunked($filename,$retbytes=true) { $chunksize = 1*(1024*1024); // how many bytes per chunk $buffer = ''; $cnt =0; $handle = fopen($filename, 'rb'); if ($handle === false) { return false; } while (!feof($handle)) { $buffer = fread($handle, $chunksize); 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; } function exists() { if( $this->_isLink ){ return true; } return file_exists($this->path.DS.$this->name); } function isLink(){ return $this->_isLink ; } /** * Get file size * * @desc Gets the file size and convert it to friendly format * @param void * @return string Returns filesize in a friendly format. */ function getSize() { if( $this->_isLink ){ return 'Link'; } $kb = 1024; $mb = 1024 * $kb; $gb = 1024 * $mb; $tb = 1024 * $gb; $size = $this->size; if ($size) { if ($size < $kb) { $file_size = $size .' '. _DML_BYTES; } elseif ($size < $mb) { $final = round($size/$kb,2); $file_size = $final .' '. _DML_KB; } elseif ($size < $gb) { $final = round($size/$mb,2); $file_size = $final .' '. _DML_MB; } elseif($size < $tb) { $final = round($size/$gb,2); $file_size = $final .' '. _DML_GB; } else { $final = round($size/$tb,2); $file_size = $final .' '. _DML_TB; } } else { if( $size == 0 ) { $file_size = _DML_EMPTY; } else { $file_size = _DML_ERROR; } } return $file_size; }
And wich php mode do you use in that website and are there really no messages n the error.log of that site?
sorry, I was out... We use Fast-CGI with SuEXEC. There are a few errors (apache2), but I did not think them relevant: Nothing in the client error log.
thanks, yes I'll try that. But as I stated, this problem did not exist on the "old" server - it was not on fast-cgi - so I suspect that it has to do with some sort of server timing on fast-cgi.