Download of large files from slow connection stops

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

  1. sageman

    sageman New Member HowtoForge Supporter

    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 HowtoForge Supporter

    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 HowtoForge Supporter

    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 HowtoForge Supporter

    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 HowtoForge Supporter

    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