Download of large files from slow connection stops

Discussion in 'Server Operation' started by sageman, Aug 17, 2011.

  1. sageman

    sageman New Member

    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
     
  2. falko

    falko Super Moderator Howtoforge Staff

    Which browser did you use? Does the same behaviour occur if you use another browser?
     
  3. sageman

    sageman New Member

    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):
     
  4. till

    till Super Moderator Staff Member ISPConfig Developer

    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.
     
  5. sageman

    sageman New Member

    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 ) );
                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 == ) {
                   
    $file_size _DML_EMPTY;
               } else {
                    
    $file_size _DML_ERROR;
               }
            }
            return 
    $file_size;
        }

     
  6. till

    till Super Moderator Staff Member ISPConfig Developer

    And wich php mode do you use in that website and are there really no messages n the error.log of that site?
     
  7. sageman

    sageman New Member

    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.
     
  8. falko

    falko Super Moderator Howtoforge Staff

  9. sageman

    sageman New Member

    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.
     

Share This Page