PHP Classes

Advanced PHP File Downloader: Retrieve files for download from remote sites

Recommend this page to a friend!
  Info   View files Example   View files View files (11)   DownloadInstall with Composer Download .zip   Reputation   Support forum   Blog    
Ratings Unique User Downloads Download Rankings
Not enough user ratingsTotal: 365 All time: 6,860 This week: 77Up
Version License PHP version Categories
php-downloader 1.0.2GNU General Publi...5HTTP, PHP 5, Files and Folders


This class can retrieve files for download from remote sites.

It can send HTTP requests to remote sites to download files and save to given load files.

The class can authenticate with a given user and password, allow to resume partially downloaded files, and can throttle the download to limit the speed of data transference.

Innovation Award
PHP Programming Innovation award nominee
November 2016
Number 9
Downloading files from remote servers in PHP is easy but if the remote server has limited bandwidth or is too busy, you may be overloading the server if you request too many files.

This package provides a solution to save bandwidth of the remote server by throttling the speed of download to a given transfer rate

Manuel Lemos
Picture of Ahmed Saad
  Performance   Level  
Name: Ahmed Saad <contact>
Classes: 10 packages by
Country: Egypt Egypt
Age: ???
All time rank: 214021 in Egypt Egypt
Week rank: 52 Up2 in Egypt Egypt Up
Innovation award
Innovation award
Nominee: 7x



require( './core/autoload.php' );

Core\Downloader as Downloader;
ini_set( 'display_errors', 1 );

error_reporting( E_ALL );
    if( isset(
$_POST[ 'download' ] ) ):

$file = is_file( './files/' . @$_POST[ 'file' ] ) ?
'./files/' . @$_POST[ 'file' ] // Download a file
$_POST[ 'file' ]; // Download string, not prepend files folder path

$save_as = !@$_POST['save_name'] ?: $_POST['save_name'];
$resumable = ( bool ) @$_POST['resumable'];
$speed = intval( @$_POST[ 'speed' ] );

$mode = @$_POST['mode'] == 'data' ? Downloader::DOWNLOAD_DATA : Downloader::DOWNLOAD_FILE;
$auth_username = @$_POST[ 'auth_username' ];
$auth_password = @$_POST[ 'auth_password' ];

$record = strlen( @$_POST[ 'record' ] ) > 1 ? 'recordBytesCallback' : ( int ) @$_POST[ 'record' ];
$auto_exit = ( bool ) @$_POST['auto_exit'];

// var_dump( $record );
        // exit();

        // Authentication Callback
function authCallback( $php_user, $php_password )
            return (
$php_user === 'login_user' && $php_password === 'login_password' ) ? true : false;

// Download Recorder Callback
function recordBytesCallback( $bytes, $file_name )
$path = './bytes.txt';

$file = fopen( $path, 'a+t' );

fwrite( $file, $file_name . ' | ' . $bytes . " Bytes \n\r" );

fclose( $file );
// file_put_contents( '', $file_name . ' | ' . $bytes );

// Start Download
$downloader = ( new Downloader( $file, $mode ) )
resumable( $resumable )
speedLimit( $speed )
setDownloadName( $save_as )
autoExit( true )
// ->authenticate( 'authCallback' )
->recordDownloaded( $record );

$auth_username && $auth_password )

$downloader->authenticate( $auth_username, $auth_password );

// Start Download


    <!DOCTYPE html>
            <title>Test Downloader Class @Ahmed Saad</title>
            <meta charset="utf-8" />
            <meta name="author" content="Ahmed Saad" />

                    /*text-align: center;*/
                    color: #666;

                    width: 400px;
                    margin: 30px auto;

                form fieldset{
                    border: 1px solid #999;
                    border-radius: 0 3px 3px 3px;
                    padding: 25px 14px;
                    margin-bottom: 20px;

                form legend{
                    border: 1px solid #999;
                    border-bottom: none;
                    border-radius: 3px 3px 0 0;
                    position: relative;
                    left: 2px;
                    bottom: -1px;
                    padding: 5px 10px;

                form fieldset, form legend{
                    background: #fcfcfc;

                    width: 250px;
                    border-radius: 4px;
                    border: 1px solid #999;
                    outline: none;

                    box-shadow: 1px 1px 4px #6ae inset, -1px -1px 1px #6ae inset;
                    border-color: #6af;

                    /*padding: 4px;*/
                    border-radius: 4px;
                    border: 1px solid rgb( 80, 150, 240 );
                    /*background: rgb( 100,170,230 );*/
                    background: -webkit-linear-gradient( rgb( 100,170,240 ) 0, rgb( 54,150,230 ) 100% );
                    color: rgb( 250, 250, 250 );
                    cursor: pointer;

                    border-color: rgb( 10, 150, 240 );

                    line-height: 15px;
                    padding: 5px;

                    border-top: 1px dashed #999;
                    margin-top: 20px;

                .files li{
                    color: rgb( 230, 100, 130 );

                form label:not([for*="mode"]):not([for*="record"])
                    width: 100px;

                form label[for*="mode"] + input, form label[for*="record"] + input
                    margin-right: 30px;

                    display: block;
                    margin: 0 auto;

                fieldset h4
                    margin: 0 auto;
                    text-align: center;
                    color: rgb( 230, 100, 130 );

                #auth_username, #auth_password{
                    width: 117px;


            <div class="container">


if( $file = @$_GET['file'] ):

                <!-- Prepare Sellected File -->
                <form method="POST">
                    <legend>Sellect Download Options</legend>
                        <h4><?= $file ?></h4>

                        <!-- Hidden File Name -->
                        <input type="hidden" name="file" value="<?= $file ?>" />

                        <!-- Save Name -->
                            <label for="save_name">Save As</label>
                            <input type="text" name="save_name" id="save_name" value="<?= $file ?>">

                        <!-- Use Resume -->
                            <label for="resumable">Use Resume</label>
                            <input type="checkbox" name="resumable" id="resumable" checked>

                        <!-- Speed Limit -->
                            <label for="speed">Speed</label>
                            <input type="text" name="speed" id="speed" placeholder="Unlimited 'use integers kBps'" value="">

                        <!-- Download Mode -->
                            <label for="file_mode">File</label>
                            <input type="radio" name="mode" id="file_mode" value="file" checked>
                            <label for="data_mode">Data</label>
                            <input type="radio" name="mode" id="data_mode" value="data">


                        <!-- Authenticate -->
                            <input type="text" name="auth_username" id="auth_username" placeholder="username">
                            <input type="text" name="auth_password" id="auth_password" placeholder="password">

                        <!-- Record Downloaded Bytes -->
                            <label>Record Bytes</label>
                            <label for="record_0">No</label>
                            <input type="radio" name="record" id="record_0" value="0" checked>
                            <label for="record_1">Yes</label>
                            <input type="radio" name="record" id="record_1" value="1">

                            <label for="record_callback">Callback</label>
                            <input type="radio" name="record" id="record_callback" value="callback">

                        <!-- Auto Exit -->
                            <label for="auto_exit">Auto Exit</label>
                            <input type="checkbox" name="auto_exit" id="auto_exit">

                        <!-- Download -->
                        <input type="submit" name="download" value="Download" />



else:// Display Form To Enter File Name
                // get $files
$files = scandir( './files/' );
$files as $key => &$file )
$file_type = @pathinfo( $file )['extension'];

$ignore = []; // [ 'php' => 1, 'html' => 1 ];

if( !is_file( './files/' . $file ) || strpos( $file, '.DS' ) === 0 || @$ignore[ $file_type ] )
$files[ $key ] );


                <form method="GET">
                    <legend>Type File Name To Download</legend>

                        <input type="text" name="file" placeholder="filename..." validate />

                        <input type="submit" value="Prepare" />

                        <div class="files">
                            <h4>existing files</h4>
if( $files )

'<ul><li>' . implode( '</li><li>', $files ) . '</li></ul>';


'<h5>No Files Found</h5>';




            <?php endif; ?>



    <? endif;



>php advanced downloader allow you to control file download process with many options and protecting real file paths


>This Package is distributed under GNU GPL V3 License


>@author Ahmed Saad <>


> 1.2.1 >> Updated at : 7 Jul 2016

>> ### Changelog :

>> Fix Byte range end ( By chardinge1 )


  1. Protect Real Files from direct access.
  2. Control download resume capability.
  3. Control download speed _(requires testing on real host to know minimum safe speed )_.
  4. Control download with authentication, ( _`WWW Basic Authentication`_ or _`callback handler`_ ).
  5. Support two diffrent modes for download, _`File mode`_ and _`Data mode`_.
  6. Change download file name * file type _extension_ might also changable only for Downloading in `Downloader::DOWNLOAD_DATA` mode .
  7. Record downloaded bytes _total bandwidth_ in a text file or add more control with a _callback handler_.
  8. Support alot of file mime types.
  9. Support _Method Chaining_.
  10. __`Designed to use namespace and autoload`__

>Note: This Class is supposed to be used in downloading processes, so throwing errors or displaying messages isn't the good idea here, So this class will depends on header status code and status text so if something happens and you want to get information, see response status code and status text.


  • just require `autoload.php` file in your script : >this autoloader will automatically load any defined class based on its namespace .

    // inside index.php require_once( './core/autoload.php' );


  • Basic file download :


    require_once( './core/autoload.php' );

    use Core\Downloader;

    $file_path = 'files/my_file.rar';

    ( new Downloader( $file_path ) )->download();


  • Advanced file download


    require_once( './core/autoload.php' );

    use Core\Downloader;

    ( new Downloader( $file_path, Downloader::DOWNLOAD_FILE ) ) // Download file in File mode ->setDownloadName( 'new_name' ) // Change download file name ->resumable( false ) // turn off resumable capability ->speedLimit( 200 ) // Limit download speed in kbyte/sec ->authenticate( 'login_name', 'login_password' ) // authenticate before downloading ->recordDownloaded( true ) // Used bandwith counter ->autoExit( true ) // Auto exit after download completed ->download(); // Start Download Process




  • `Download Mode`

    there are two types of downloading mode:

    > Downloader::DOWNLOAD_FILE

    > Downloader::DATA

    are defined as the second arguments for Downloader constructor, default one is file mode

    - file mode : `Downloader::DOWNLOAD_FILE`

    > in file mode the downloaded file must be file and exists and readabe, otherwise an header status code 404 for file not found, or 405 for non readable files

    >if we change download name file type and extension will not be affected by the new name, only file name will be changed

    - data mode : `Downloader::DOWNLOAD_DATA`

    > data mode can download a file or string or any thing if the downloaded is file it will download it, other wise it will consider that we are downloading a basic txt file, so it will set extension to txt and and give a default filename

    >> __Note :__

    >> Downloading in data mode will change last modified time to the downloaded time __Current download time*__.

    >> * to controll downloaded file format, you can use _`setDownloadName()`_ method then the given extension will be used as file type


    // File Mode ( new Downloader( 'files/file.mp3' ) ) ->setDownloadName( 'newname.mp4' ) ->download(); // Downloaded file name will be newname.mp3, mp4 will be ignored

    // Data Mode ( new Downloader( 'files/file.mp3', Downloader::DOWNLOAD_DATA ) ) ->setDownloadName( 'newname.mp4' ) ->download(); // Downloaded file name will be newname.mp4, and couldn't be opened due to wrong extension, So becareful while downloading in data mode


  • `Downloader::setDownloadName( string $filename )`

    change downloaded file name

    > this method behaviour depends also on download mode :

    >> if new extenstion supplied :

    >> in file mode ===> only file name will be changed and extension will be ignored .

    >> in data mode ===> file name and type will be change .


    // assuming original file is 'file.mp3'

    // Download in File Mode $downloader->setDownloadName( 'another_name.avi' ); // another_name.mp3

    // Download in Data Mode $downloader->setDownloadName( 'another_name.avi' ); // another_name.avi

    $downloader->setDownloadName( 'another_name' ); // another_name.mp3 ( if file.mp3 exists ) // another_name.txt ( if file.mp3 doesn't exists )


  • `Downloader::resumable( bool $bool )`

    turn on or off resume capability

    > Downloader Default behaviour is to use resume


    $downloader->resumable(); // turn on

    $downloader->resumable( true ); // turn on

    $downloader->resumable( false ); // Turn off


  • `Downloader::speedLimit( int $speed )`

    $speed is integer represent downlowd speed in Kilobytes per second

    > __Note :__

    > Speed Limiting depends on micro sleep, So, Becarefull while using speed limit, in any value it works very well and almost accurate in local host testing. in real host you should test to know the best safe minimum speed because in some hosts speed limit may cause download corrupt as server may close connection due to script sleeping

    > Limited speed is defined for one connection, so while using resume and downloading with download programs such as IDM, there eill be multi connections, every single connection will download with defined speed, so overall speed will be many doubles of defined speed.

    // Limit speed to 100 kB/s $downloader->speedLimit( 100 );

  Files folder image Files  
File Role Description
Files folder imagecore (4 files)
Files folder imagefiles (3 files)
Accessible without login Plain text file get_file.php Example Example script
Accessible without login Plain text file index.php Example Example script
Accessible without login Plain text file LICENSE Lic. License text
Accessible without login Plain text file Doc. Documentation

  Files folder image Files  /  core  
File Role Description
  Accessible without login Plain text file autoload.php Aux. Auxiliary script
  Plain text file downloader.php Class Class source
  Accessible without login Plain text file extensions_mime.php Conf. Configuration script
  Plain text file http_error_response_trait.php Class Class source

  Files folder image Files  /  files  
File Role Description
  Accessible without login Plain text file file.txt Doc. Documentation
  Accessible without login Plain text file html_file.html Data Auxiliar data
  Accessible without login Plain text file phpfile.php Aux. Auxiliary script

 Version Control Unique User Downloads Download Rankings  
This week:0
All time:6,860
This week:77Up