PHP在不离开当前页面的情况下制作下载计数器

时间:2014-04-27 21:55:37

标签: php html download counter

我尝试用PHP创建一个下载计数器。 我创建的脚本有效,但是当我单击下载链接时,脚本会将我发送到空白页面。下载和计算时是否可以留在页面上?

这是我的download.php文件的代码:

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

<html>
<head>

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

</head>

<body>

<?php

$fp = fopen("counter.txt", "r");
$count = fread($fp, 1024);
fclose($fp);
$count = $count + 1;

$fp = fopen("counter.txt", "w");
fwrite($fp, $count);
fclose($fp);


?>

</body>
</html>

我的index.php中的链接如何:

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

非常感谢提前!

4 个答案:

答案 0 :(得分:4)

好了,因为这里缺少大部分代码是一个例子,基本上你需要调用download.php文件中的计数器代码,并在执行计数器代码和设置下载头之后传递文件内容。也要警惕或允许恶意人员通过将文件名传递给下载功能从服务器下载任何文件。 download.php?file=index.php

<?php 
function get_download_count($file=null){
    $counters = './counters/';
    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;
}
?>
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title></title>
</head>

<body>

<a href="./download.php?file=exampleA.zip">exampleA.zip</a> (Downloaded <?php echo get_download_count('exampleA.zip');?> times)<br>
<a href="./download.php?file=exampleB.zip">exampleB.zip</a> (Downloaded <?php echo get_download_count('exampleB.zip');?> times)<br>

</body>
</html>

download.php ,因为您可以看到它不输出HTML,因为这会破坏文件。

<?php 
//where the files are
$downloads_folder = './files/';
$counters_folder = './counters/';

//has a file name been passed?
if(!empty($_GET['file'])){
    //protect from people getting other files
    $file = basename($_GET['file']);

    //does the file exist?
    if(file_exists($downloads_folder.$file)){

        //update counter - add if dont exist
        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);
        }

        //set force download headers
        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)));

        //open and output file contents
        $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!');
    }
}else{
    exit(header("Location: ./index.php"));
}
?>

确保检查$downloads_folder变量是否正确。希望它有所帮助。

<强> Download Full example code.

答案 1 :(得分:0)

尝试使用php标头重定向而不是JS或元标记重定向:

<?php
//counter code
$fp = fopen("counter.txt", "r");
$count = fread($fp, 1024);
fclose($fp);
$count = $count + 1;

$fp = fopen("counter.txt", "w");
fwrite($fp, $count);
fclose($fp);

// redirect
header("location: ".$_GET["Down"]);
exit;

还要确保标题前没有输出任何内容。

http://www.php.net/manual/en/function.header.php

同样对于链接,如果仍然无效,请尝试添加目标attr:

<a href="download.php?Down=download.zip" target="_new">download</a>

答案 2 :(得分:0)

我想改善Lawrence Cherone的答案。下载计数器imho应该是透明的,因此它更安全,没有人应该直接访问php脚本。最后我集成了jquery,所以计数器通过ajax实时更新...所以没有必要重新加载页面来查看结果......

.htaccess(位于root / files /中)

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

doing_download.php(位于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(位于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(位于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(位于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(位于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(位于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!

我希望我根据Lawrence Cherone的答案回答任何问题:) @Lawrence Cherone:干得好!!!

答案 3 :(得分:0)

error CS1022: Type or namespace definition, or end-of-file expected