public function send($file_path, $withDisposition=TRUE) {
        
        if (!is_readable($file_path)) {
            throw new \Exception('File not found or inaccessible!');
        }

        $size = filesize($file_path);
        if (!$this->disposition) {
            $this->disposition = $this->name($file_path);
        }
        
        if (!$this->type) {
            $this->type = $this->getContentType($file_path);
        }

        //turn off output buffering to decrease cpu usage
        $this->cleanAll();
        
        // required for IE, otherwise Content-Disposition may be ignored
        if (ini_get('zlib.output_compression')) {
            ini_set('zlib.output_compression', 'Off');
        }

        header('Content-Type: ' . $this->type);
        if ($withDisposition) {
            header('Content-Disposition: attachment; filename="' . $this->disposition . '"');
        }
        header('Accept-Ranges: bytes');

        // The three lines below basically make the
        // download non-cacheable 
        header("Cache-control: private");
        header('Pragma: private');
        header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");

        // multipart-download and download resuming support
        if (isset($_SERVER['HTTP_RANGE'])) {
            list($a, $range) = explode("=", $_SERVER['HTTP_RANGE'], 2);
            list($range) = explode(",", $range, 2);
            list($range, $range_end) = explode("-", $range);
            $range = intval($range);
            if (!$range_end) {
                $range_end = $size - 1;
            } else {
                $range_end = intval($range_end);
            }

            $new_length = $range_end - $range + 1;
            header("HTTP/1.1 206 Partial Content");
            header("Content-Length: $new_length");
            header("Content-Range: bytes $range-$range_end/$size");
        } else {
            $new_length = $size;
            header("Content-Length: " . $size);
        }

        /* output the file itself */
        $chunksize = $this->bytes; //you may want to change this
        $bytes_send = 0;
        
        $file = @fopen($file_path, 'rb');
        if ($file) {
            if (isset($_SERVER['HTTP_RANGE'])) {
                fseek($file, $range);
            }

            while (!feof($file) && (!connection_aborted()) && ($bytes_send < $new_length) ) {
                $buffer = fread($file, $chunksize);
                echo($buffer); //echo($buffer); // is also possible
                flush();
                usleep($this->sec * 1000000);
                $bytes_send += strlen($buffer);
            }
            fclose($file);
        } else {
            throw new \Exception('Error - can not open file.');
        }
    }
public function send($file_path, $withDisposition=TRUE) {
        
        if (!is_readable($file_path)) {
            throw new \Exception('File not found or inaccessible!');
        }

        $size = filesize($file_path);
        if (!$this->disposition) {
            $this->disposition = $this->name($file_path);
        }
        
        if (!$this->type) {
            $this->type = $this->getContentType($file_path);
        }

        //turn off output buffering to decrease cpu usage
        $this->cleanAll();
        
        // required for IE, otherwise Content-Disposition may be ignored
        if (ini_get('zlib.output_compression')) {
            ini_set('zlib.output_compression', 'Off');
        }

        header('Content-Type: ' . $this->type);
        if ($withDisposition) {
            header('Content-Disposition: attachment; filename="' . $this->disposition . '"');
        }
        header('Accept-Ranges: bytes');

        // The three lines below basically make the
        // download non-cacheable 
        header("Cache-control: private");
        header('Pragma: private');
        header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");

        // multipart-download and download resuming support
        if (isset($_SERVER['HTTP_RANGE'])) {
            list($a, $range) = explode("=", $_SERVER['HTTP_RANGE'], 2);
            list($range) = explode(",", $range, 2);
            list($range, $range_end) = explode("-", $range);
            $range = intval($range);
            if (!$range_end) {
                $range_end = $size - 1;
            } else {
                $range_end = intval($range_end);
            }

            $new_length = $range_end - $range + 1;
            header("HTTP/1.1 206 Partial Content");
            header("Content-Length: $new_length");
            header("Content-Range: bytes $range-$range_end/$size");
        } else {
            $new_length = $size;
            header("Content-Length: " . $size);
        }

        /* output the file itself */
        $chunksize = $this->bytes; //you may want to change this
        $bytes_send = 0;
        
        $file = @fopen($file_path, 'rb');
        if ($file) {
            if (isset($_SERVER['HTTP_RANGE'])) {
                fseek($file, $range);
            }

            while (!feof($file) && (!connection_aborted()) && ($bytes_send < $new_length) ) {
                $buffer = fread($file, $chunksize);
                echo($buffer); //echo($buffer); // is also possible
                flush();
                usleep($this->sec * 1000000);
                $bytes_send += strlen($buffer);
            }
            fclose($file);
        } else {
            throw new \Exception('Error - can not open file.');
        }
    }
public function send ( $ file_path , $ withDisposition = TRUE ) { if ( ! is_readable ( $ file_path ) ) { throw new \ Exception ( 'File not found or inaccessible!' ) ; } $ size = filesize ( $ file_path ) ; if ( ! $ this -> disposition ) { $ this -> disposition = $ this -> name ( $ file_path ) ; } if ( ! $ this -> type ) { $ this -> type = $ this -> getContentType ( $ file_path ) ; } //turn off output buffering to decrease cpu usage $ this -> cleanAll ( ) ; // required for IE, otherwise Content-Disposition may be ignored if ( ini_get ( 'zlib.output_compression' ) ) { ini_set ( 'zlib.output_compression' , 'Off' ) ; } header ( 'Content-Type: ' . $ this -> type ) ; if ( $ withDisposition ) { header ( 'Content-Disposition: attachment; filename="' . $ this -> disposition . '"' ) ; } header ( 'Accept-Ranges: bytes' ) ; // The three lines below basically make the // download non-cacheable  header ( "Cache-control: private" ) ; header ( 'Pragma: private' ) ; header ( "Expires: Mon, 26 Jul 1997 05:00:00 GMT" ) ; // multipart-download and download resuming support if ( isset ( $ _SERVER [ 'HTTP_RANGE' ] ) ) { list ( $ a , $ range ) = explode ( "=" , $ _SERVER [ 'HTTP_RANGE' ] , 2 ) ; list ( $ range ) = explode ( "," , $ range , 2 ) ; list ( $ range , $ range_end ) = explode ( "-" , $ range ) ; $ range = intval ( $ range ) ; if ( ! $ range_end ) { $ range_end = $ size - 1 ; } else { $ range_end = intval ( $ range_end ) ; } $ new_length = $ range_end - $ range + 1 ; header ( "HTTP/1.1 206 Partial Content" ) ; header ( "Content-Length: $new_length" ) ; header ( "Content-Range: bytes $range-$range_end/$size" ) ; } else { $ new_length = $ size ; header ( "Content-Length: " . $ size ) ; } /* output the file itself */ $ chunksize = $ this -> bytes ; //you may want to change this $ bytes_send = 0 ; $ file = @ fopen ( $ file_path , 'rb' ) ; if ( $ file ) { if ( isset ( $ _SERVER [ 'HTTP_RANGE' ] ) ) { fseek ( $ file , $ range ) ; } while ( ! feof ( $ file ) && ( ! connection_aborted ( ) ) && ( $ bytes_send < $ new_length ) ) { $ buffer = fread ( $ file , $ chunksize ) ; echo ( $ buffer ) ; //echo($buffer); // is also possible flush ( ) ; usleep ( $ this -> sec * 1000000 ) ; $ bytes_send += strlen ( $ buffer ) ; } fclose ( $ file ) ; } else { throw new \ Exception ( 'Error - can not open file.' ) ; } }
Sets-up headers and starts transfering bytes

@param string  $file_path
@param boolean $withDisposition
@throws Exception
Sets - up headers and starts transfering bytes