1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Download Script in PHP with a Countdown Timer before download Begins

Discussion in 'PHP' started by ManzZup, Aug 6, 2011.

  1. ManzZup

    ManzZup New Member

    Joined:
    May 9, 2009
    Messages:
    278
    Likes Received:
    43
    Trophy Points:
    0
    Occupation:
    Production Manager:Software @ ZONTEK
    Location:
    Sri Lanka
    Home Page:
    Got the vacations and so it's coding time. Pretty basic php based download script with a counter before starting the download, you may have seen those kind of script sources all around. But I made some arrangements for this code to make it a bit more than a simple downloading script. Lets start then.

    Background



    What is a Download Script?

    The best way to explain is the sites like sourceforge.net and cnet.com where when you select a file to download, it wont give you a direct link, but directs you to a page where a download will start after soem seconds or immediately or even you can select another mirror and stuff.

    Why to use a Download Script?
    1. It makes your site/application more professional.
    2. You can easily implement things like download counter to the page.
    3. Can reduce a bit of certain automated scripts from downloading your script
    How it Works?

    Those scripts change the header content type through the script so the browser identifies anything comming from that script as something downloadable.
    1. download.php -> handle the things that the user sees
    2. downloader.php -> prepares and send the file to the user without showing to the user
    Logic: Most of the time, download.php will be using an iframe to load the downloader.php and hence the user see no difference

    The Code


    1. First we need to make a table with the links to the files. Use the following query for the table. You should add ALL the links that you allow the use to download. The download script is called from the "ID" of the selected product.

      Code:
      --
      -- Table structure for table `downloads`
      --
      
      CREATE TABLE IF NOT EXISTS `downloads` (
        `ID` int(11) NOT NULL AUTO_INCREMENT,
        `Name` text NOT NULL,
        `Link` text NOT NULL,
        `Counter` int(11) NOT NULL,
        PRIMARY KEY (`ID`)
      ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;
      
    2. So we have the the table, add up some products. For this remeber the following tips:
      • We will be placing our download script in the root directory so you can easily access all the files elsewhere
      • Have relative links, and reduce having spaces and long names as file names.

      Let's add up some records as per the following fields:
      • ID - This is an Auto Increment value saying the product ID
      • Name - Product Name, used for the convenience of the user
      • Link - The MOST vital part, holds a RELATIVE link for the file
      • Count - Take how many time the file is downloaded
      Code:
      INSERT INTO `downloads` (`ID`, `Name`, `Link`, `Counter`) VALUES
      (1, 'Product1', 'files/prod1.zip', 0);
      
    3. Done with databases, now lets got for the real scripting. First we need a download.php script which will be the one interacting with the user
      ex: http://mysite.com/download.php?id=1

      download.php
      PHP:
      <?php
      define
      ("db_user","root"); //your databse user name
      define("db_pwd",""); //your database password
      define("db_name","zontek");  //your databasename
      define("db_host","127.0.0.1");
           
            
      //First getting the id specified as download.php?id=1
          
      $id htmlspecialchars($_GET['id']);
          
      //This variable is a bool to check for any error, as we should have tight security
          
      $error false;
          
      //Connecting to the database
          
      $conn mysql_connect(db_host,db_user,db_pwd);
          if(!(
      $conn)) echo "Failed To Connect To The Database!";
          else{   
              if(
      mysql_select_db(db_name,$conn)){
                  try{
                      
      $qry "SELECT Name,Link FROM downloads WHERE ID=$id";
                      
      $result mysql_query($qry);
                      
      //Check whether there's a result with the id number
                      
      if(mysql_num_rows($result)==1){
                          while(
      $rows mysql_fetch_array($result)){
                              
      //If there's one take the details into variables
                              
      $nam $rows['Name'];
                              
      $link $rows['Link'];
                          }
                          
      //Updating the counter by 1
                          
      $qry "UPDATE downloads SET Counter = Counter+1";
                          
      mysql_query($qry);
                      }else{ 
      $error true; }
                  }catch(
      Exception $e){
                      
      //If an Exception occurrs make $error true
                      
      $error true;
                  }       
           
      // At last check whether $error is true, if so immediatly redirect to the home page so that an attacker cannot take use of any error
           
      if($errorheader("Location: index.php");           
                 
              }
           }
      ?>
      <html>
      <head>
      <title>Download Script</title>
      <script type="text/javascript">
          window.onload = function(){
              //Creates a new iframe
              var ele = document.createElement('iframe');
              //Navigate the iframe to the downloader.php which in turn return the file
              ele.src = "downloader.php?id=<?php echo $id?>";
              //Hide the stuff from the user
              ele.style.display = "none";
              //Add the iframe to the document body
              document.body.appendChild(ele);
          }
      </script>
      </head>
      <body>
      Thank You For Downloading <?php echo $nam?> <!-- note the use of the Name field to show the user what he is downloading -->
      </body>
      </html>
    4. Now we make the downloader.php which will recieve the same ID as the download.php and then it will return a file back.

      downloader.php
      PHP:
      <?php
      define
      ("db_user","root"); //your databse user name
      define("db_pwd",""); //your database password
      define("db_name","zontek");  //your databasename
      define("db_host","127.0.0.1");
           
       
      $id htmlspecialchars($_GET['id']);
       
      $error false;
          
      $conn mysql_connect(db_host,db_user,db_pwd);
          if(!(
      $conn)) echo "Failed To Connect To The Database!";
          else{   
              if(
      mysql_select_db(db_name,$conn)){
                  
      $qry "SELECT Link FROM downloads WHERE ID=$id";
                  try{
                      
      $result mysql_query($qry);
                      if(
      mysql_num_rows($result)==1){
                          while(
      $rows mysql_fetch_array($result)){
                              
      $f=$rows['Link'];
                          }
                         
                          
      //Code above this part was more or less the same as the previous, but the code below plays an IMPORTANT role
                         
                          //First we need a name to the file we are sending to the user, by defualt it will be saying something which include the complete path + file name and some blahh. But it is better to have the same sweet name you put for the original fiel to be here as well :D
                          //pathinfo returns an array of information
                          
      $path pathinfo($f);
                          
      //basename say the filename+extension
                          
      $n $path['basename'];
                          
      //NOW comes the action, this statement would say that WHATEVER output given by the script is given in form of an octet-stream, or else to make it easy an application or downloadable
                          
      header('Content-type: application/octet-stream');
                          
      //This would be the one to rename the file
                          
      header('Content-Disposition: attachment; filename='.$n.'');
                          
      //Finally it reads the file and prepare the output
                          
      readfile($f);
                          
      //If you goto to the same page with your browser a download will start immediately
                      
      }else $error true;
                  }catch(
      Exception $e){
                      
      $error true;
                  }
                  if(
      $errorheader("Location: index.php");
              }
        }
      ?>
    5. Now everything's fine, when you goto http://mysite.com/download.php?id=1 and if you have the file prod1.zip in files directory (files/prod1.zip) your download will start immediately or giveout a status bar saying a file is going to download.

      Lets put up a bit of a code so that a counter of 5 second go before the thing starts so that if the user doesnot wanna download the file he can quit before it. For that edit the html part of download.php as follow:
      PHP:
      <html>
      <head>
      <title>Download Script</title>
      <script type="text/javascript">
          //Count to 5 seconds
          var c = 6;
          window.onload = function(){
              count(); //Execute the method
          }   
          function count(){
              c -= 1;
              //If the counter is within range we put the seconds remaining to the <span> below
              if(c>=0) document.getElementById("time").innerText = " in " + c + " Seconds";
              else{
                  //After the counter download the file and end the timer
                  document.getElementById("time").innerText = "Now";
                  download();
                  return;
              }
              var counter2 = setTimeout("count()",1000);
              return;
          }
          function download(){
              //Creates a new iframe
              var ele = document.createElement('iframe');
              //Navigate the iframe to the downloader.php which in turn return the file
              ele.src = "downloader.php?id=<?php echo $id?>";
              //Hide the stuff from the user
              ele.style.display = "none";
              //Add the iframe to the document body
              document.body.appendChild(ele);
          }
      </script>
      </head>
      <body>
      Thank You For Downloading <?php echo $nam?> <!-- note the use of the Name field to show the user what he is downloading --><br />
      Your download will start <span id="time"></span>.
      </body>
      </html>
      Now the new file is like
      download.php
      PHP:
      <?php
      define
      ("db_user","root"); //your databse user name
      define("db_pwd",""); //your database password
      define("db_name","zontek");  //your databasename
      define("db_host","127.0.0.1");
           
            
      //First getting the id specified as download.php?id=1
          
      $id htmlspecialchars($_GET['id']);
          
      //This variable is a bool to check for any error, as we should have tight security
          
      $error false;
          
      //Connecting to the database
          
      $conn mysql_connect(db_host,db_user,db_pwd);
          if(!(
      $conn)) echo "Failed To Connect To The Database!";
          else{   
              if(
      mysql_select_db(db_name,$conn)){
                  try{
                      
      $qry "SELECT Name,Link FROM downloads WHERE ID=$id";
                      
      $result mysql_query($qry);
                      
      //Check whether there's a result with the id number
                      
      if(mysql_num_rows($result)==1){
                          while(
      $rows mysql_fetch_array($result)){
                              
      //If there's one take the details into variables
                              
      $nam $rows['Name'];
                              
      $link $rows['Link'];
                          }
                          
      //Updating the counter by 1
                          
      $qry "UPDATE downloads SET Counter = Counter+1";
                          
      mysql_query($qry);
                      }else{ 
      $error true; }
                  }catch(
      Exception $e){
                      
      //If an Exception occurrs make $error true
                      
      $error true;
                  }       
           
      // At last check whether $error is true, if so immediatly redirect to the home page so that an attacker cannot take use of any error
           
      if($errorheader("Location: index.php");           
                 
              }
           }
      ?>
      <html>
      <head>
      <title>Download Script</title>
      <script type="text/javascript">
          //Count to 5 seconds
          var c = 6;
          window.onload = function(){
              count(); //Execute the method
          }   
          function count(){
              c -= 1;
              //If the counter is within range we put the seconds remaining to the <span> below
              if(c>=0) document.getElementById("time").innerText = " in " + c + " Seconds";
              else{
                  //After the counter download the file and end the timer
                  document.getElementById("time").innerText = "Now";
                  download();
                  return;
              }
              var counter2 = setTimeout("count()",1000);
              return;
          }
          function download(){
              //Creates a new iframe
              var ele = document.createElement('iframe');
              //Navigate the iframe to the downloader.php which in turn return the file
              ele.src = "downloader.php?id=<?php echo $id?>";
              //Hide the stuff from the user
              ele.style.display = "none";
              //Add the iframe to the document body
              document.body.appendChild(ele);
          }
      </script>
      </head>
      <body>
      Thank You For Downloading <?php echo $nam?> <!-- note the use of the Name field to show the user what he is downloading --><br />
      Your download will start <span id="time"></span>.
      </body>
      </html>
    So that's it, you can implement this easily to your site and such simple method will make you site look more user friendly and professional to the users and even your management of files become easier.

    Script Live In Action : http://zontek.zzl.org/download.php?id=1

    See ya all again soon with more advance downloader [probably captcha] Till then byee and thank alot for reading :D
     
  2. dean8710

    dean8710 New Member

    Joined:
    Aug 3, 2011
    Messages:
    8
    Likes Received:
    0
    Trophy Points:
    0
    Location:
    Petaling Jaya
    5. Page Not Found - 404 Error Page

    Oops! Google Chrome could not connect to zontek.zzl.org
     
  3. ManzZup

    ManzZup New Member

    Joined:
    May 9, 2009
    Messages:
    278
    Likes Received:
    43
    Trophy Points:
    0
    Occupation:
    Production Manager:Software @ ZONTEK
    Location:
    Sri Lanka
    Home Page:
    sorry about that
    some spamming issues of the site due those spammer on ma forum
    will be fixing the site / links soon
    sorry again
     
  4. ManzZup

    ManzZup New Member

    Joined:
    May 9, 2009
    Messages:
    278
    Likes Received:
    43
    Trophy Points:
    0
    Occupation:
    Production Manager:Software @ ZONTEK
    Location:
    Sri Lanka
    Home Page:
    site up and running
    links are working :D
     
  5. john1110

    john1110 New Member

    Joined:
    Jul 25, 2011
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    good information
     
  6. hanleyhansen

    hanleyhansen New Member

    Joined:
    Jan 24, 2008
    Messages:
    336
    Likes Received:
    8
    Trophy Points:
    0
    Occupation:
    Drupal Developer/LAMP Developer
    Location:
    Clifton
    Home Page:
    Great article!! Thanks for sharing.
     
  7. nabila1230

    nabila1230 Banned

    Joined:
    Sep 13, 2011
    Messages:
    4
    Likes Received:
    0
    Trophy Points:
    0
    its really great article, i really find it very help full, keep it up and appreciated
     
  8. dean8710

    dean8710 New Member

    Joined:
    Aug 3, 2011
    Messages:
    8
    Likes Received:
    0
    Trophy Points:
    0
    Location:
    Petaling Jaya
  9. ManzZup

    ManzZup New Member

    Joined:
    May 9, 2009
    Messages:
    278
    Likes Received:
    43
    Trophy Points:
    0
    Occupation:
    Production Manager:Software @ ZONTEK
    Location:
    Sri Lanka
    Home Page:
    sorry about that, i'll update all the links
     
  10. ManzZup

    ManzZup New Member

    Joined:
    May 9, 2009
    Messages:
    278
    Likes Received:
    43
    Trophy Points:
    0
    Occupation:
    Production Manager:Software @ ZONTEK
    Location:
    Sri Lanka
    Home Page:

Share This Page