1

I am using a simple downloadcounter which counts the downloads in a txt file. In the folder downloads i have a file called download.php in which is this code:

<?php
$Down=$_GET['Down'];
?>

<html>
<head>
<meta http-equiv="refresh" content="0;url=<?php echo $Down; ?>"> 
</head>
<body>

<?php

$filePath = $Down.".txt";

// If file exists, read current count from it, otherwise, initialize it to 0
$count = file_exists($filePath) ? file_get_contents($filePath) : 0;

// Increment the count and overwrite the file, writing the new value
file_put_contents($filePath, ++$count);

// Display current download count
echo "Downloads:" . $count;

?> 

</body>
</html>

The link i use is in a file outside the downloads folder and looks like this:

<a href="downloads/download.php?Down=download.zip">Download</a>

This works fine so far. After clicking on the link the url gives me: http://localhost/downloads/download.php?Down=download.zip and the zip file is downloaded.

What i want to achieve: redirect immediately back to the link page; i added header Location after the echo in download.php

// Display current download count
//echo "Downloads:" . $count;
header('Location: http://localhost/link.php');

Now he goes immediately back and he does increment with 1 in the text file but the zip file is not downloaded anymore. Why is the file not downloaded anymore after the redirect?

nuet maessen
  • 131
  • 10

3 Answers3

3

The main approach is this that you go to "after" page first then start the download. In your case, You want to redirect user to link.php, so you need to redirect the page to link.php first, which should have the html refresh meta-equiv tag with your real download url, It will download the file and won't affect the current page.

As your before and after pages are the same, you can pass an argument with link.php?download=true. If download is true then print the meta-equiv tag.

I hope you get the basic idea.

Prateek
  • 368
  • 3
  • 16
2

Try the following to download the file.

header('Content-Disposition: attachment; filename="'.$Down.'"');
RJ Anoop
  • 763
  • 13
  • 26
1

I used another method, the user clicks on a link on download link page and without leaving the current page a counter is incremented in real time. So there isn't need to redirect to another or same page because the file is counted transparently without leaving the current page. The download counter, imho, should be transparent so it's more secure, nobody should have access directly to php scripts. Also note that the my preferred method is restricting action using file extension so an user can download only certain files, also note that a better method is using .htaccess intercepting the files matched and passing them to php script... Finally I also integrated into my project jquery so the counter is updated in real time via ajax... so there is no need to reload the page to see the results...

.htaccess (located in root/files/)

RewriteEngine on
RewriteRule ^(.*).(rar|zip)$ /php/doing_download.php?file=$1.$2 [R,L]

doing_download.php (located in root/php)

<?php
  $downloads_folder = $_SERVER['DOCUMENT_ROOT'] . '/files/';
  $counters_folder = $_SERVER['DOCUMENT_ROOT'] . '/files/counter/';
  if (!empty($_GET['file'])) {
    $file = basename($_GET['file']);
    $type = array("zip", "rar");
    $exts = strtolower(substr(strrchr($file, "."), 1));
    if (!in_array($exts, $type)) {
      header("HTTP/1.0 403 Forbidden");
      exit('File not allowed!');
    } else {
      if (file_exists($downloads_folder . $file)) {
        if (file_exists($counters_folder . md5($file) . '_counter.txt')) {
          $fp = fopen($counters_folder . md5($file) . '_counter.txt', "r");
          $count = fread($fp, 1024);
          fclose($fp);
          $fp = fopen($counters_folder . md5($file) . '_counter.txt', "w");
          fwrite($fp, $count + 1);
          fclose($fp);
        } else {
          $fp = fopen($counters_folder . md5($file) . '_counter.txt', "w+");
          fwrite($fp, 1);
          fclose($fp);
        }
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="' . $file . '"');
        header('Content-Transfer-Encoding: binary');
        header('Connection: Keep-Alive');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
        header('Content-Length: ' . sprintf("%u", filesize($downloads_folder . $file)));
        $fh = fopen($downloads_folder . $file, "rb");
        while (!feof($fh)) {
          echo fgets($fh);
          flush();
        }
        fclose($fh);
        exit;
      } else {
        header("HTTP/1.0 404 Not Found");
        exit('File not found!');
      }
    }
  }
?>

count_download.php (located in root/php/)

<?php
  function get_download_count($file = null) {
    $counters = $_SERVER['DOCUMENT_ROOT'] . '/files/counter/';
    if ($file == null) return 0;
    $count = 0;
    if (file_exists($counters . md5($file) . '_counter.txt')) {
      $fp = fopen($counters . md5($file) . '_counter.txt', "r");
      $count = fread($fp, 1024);
      fclose($fp);
    } else {
      $fp = fopen($counters . md5($file) . '_counter.txt', "w+");
      fwrite($fp, $count);
      fclose($fp);
    }
    return $count;
  }
?>

call_download.php (located in root/php)

<?php
  include($_SERVER["DOCUMENT_ROOT"] . "/php/count_download.php");
  $item['item1'] = get_download_count('exampleA.zip');
  $item['item2'] = get_download_count('exampleB.zip');
  echo json_encode($item);
?>

static_download.php (located in root/php)

<?php
  include($_SERVER["DOCUMENT_ROOT"] . "/php/count_download.php");
  $item['item1'] = get_download_count('exampleA.zip');
  $item['item2'] = get_download_count('exampleB.zip');
?>

download.js (located in root/jsc/)

$(document).ready(function() {
  $.ajaxSetup({cache: false});
  getStatus();
});
function getStatus() {
  $.getJSON('php/call_download.php', function(data) {
    $('#item1').html(data.item1);
    $('#item2').html(data.item2);
  });
  setTimeout("getStatus()",1000);
}

index.php (located in root/)

<?php include($_SERVER["DOCUMENT_ROOT"] . "/php/static_download.php"); ?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Download Page</title>
<script type="text/javascript" src="jsc/jquery.min.js"></script>
<script type="text/javascript" src="jsc/download.js"></script>
</head>
<body>
File: <a href="files/exampleA.zip">exampleA.zip</a>&nbsp; - &nbsp;Downloaded <span id="item1"><?php echo $item['item1']; ?></span> Times<br />
File: <a href="files/exampleB.zip">exampleB.zip</a>&nbsp; - &nbsp;Downloaded <span id="item2"><?php echo $item['item2']; ?></span> Times<br />
File: <a href="test/test.zip">test.zip</a><!-- this file never will be counted since is located in other folder --><br />
</body>
</html>

Here, you can download all files and test them!

Based on answer of Lawrence Cherone and me: https://stackoverflow.com/a/29105023/4432311

PS: you may need to change folders in php scripts... my scripts assume that you are testing in the root of your server...

Community
  • 1
  • 1
Alessandro
  • 900
  • 12
  • 23