通过PHP提供主机文件,日志下载和主机统计信息?

时间:2011-08-10 02:35:23

标签: php

我是一个试图在这里尝试PHP的.NET人,所以现在完全不在我的舒适区。我想要做的是拥有3个文件:

  • download.php

    (a)包含查找文件名的ID(所以download.php?file=11 querystring告诉我应该托管abc.zip)

    (b)将此下载记录到stats.log

    的一些代码

    (c)一对header()次来电和readfile()来电,类似于对this question

    的回答
  • stats.log :一个简单的日志文件,可能类似于以下示例。这允许通过简单地添加一行文本来完成日志记录,但允许我不时地压缩它。


abc.zip 1234
xyz.zip 4321
abc.zip 1
abc.zip 1
abc.zip 1
xyz.zip 1
abc.zip 1

  • stats.php :这最终是提供统计信息的PHP文件。它们可以是实时的或接近实时的,也许每分钟重新读取文件并缓存它或其他任何东西。我并不在乎,这不会经常发生,但我确实需要确保这不是一个非常昂贵的操作。这不一定是一个漂亮的页面。人类可以很容易地阅读的东西是最重要的,所以那里没有花哨的要求。对于stats.log的上述示例,我希望这样做以下内容:

abc.zip: 1238 downloads
xyz.zip: 4322 downloads

最终,我不想要数据库或涉及此的任何其他系统。我只有FTP访问服务器,所以除了将脚本放入目录之外,我真的做不了什么。我意识到我需要确保该脚本具有stats.txt的写权限,这很好。

所以我的问题。我有很多,但我相信对于那些了解PHP的人来说,这些都很容易。

  1. 我认为通过设置标头和使用readfile可以理解download.php的托管部分。但是,我怎么能有一组表示文件ID和文件名的键/值对?如果我在.NET中,我可以做类似的事情:var foo = new Dictionary<int, string> {{11, "abc.zip"}, {12, "xyz.zip"}}但我不知道这在PHP中是什么样的。
  2. 如何获得查询字符串?我需要从URL“stuff / download.php?file = 11”中取出并从11中取出我的查询集合中的“abc.zip”。
  3. 如何将换行符写入stats.log文件?
  4. 如何循环浏览stats.log脚本中的stats.php文件来统计并托管这些统计信息?
  5. 奖金问题:如何缓存步骤4中的结果,并且每分钟/小时/或其他任何内容只读取一次文件?
  6. 如果有人能够回答至少大部分问题,我可能会填补一些空白,但请确保我们感激不尽! :)

2 个答案:

答案 0 :(得分:1)

1-您正在寻找array例如

 $files=array(11=>'abc.zip',
             12=>'xyz.zip');

2-查询字符串由超级全局$_GET访问,因此在您的情况下$_GET['file']包含您感兴趣的数据。

3,4,5    我建议存储JSON编码的信息。 e.g。

$rawInfo=file_get_contents('stats.log');
$Info=json_decode($rawInfo,true);
if(isset($Info[$_GET['file']])){
    $Info[$_GET['file']]++;
}else{
    $Info[$_GET['file']]=1;
}
$rawInfo=json_encode($Info);
$h=fopen('stats.log','c');// If $h is false, you couldn't open the file
flock($h,LOCK_EX);// lock the file
$b=fwrite($h,$rawInfo);// if $b is not greater than 0, nothing was written
flock($h,LOCK_UN);
fclose($h);
//And then actually serve the file requested

这样做的好处是可以以有用的格式存储信息。

每当您提取json_decode ed数据时,它的格式为array,您需要知道如何处理。

stats.php可能看起来像这样:

$rStats=file_get_contents('stats.log');
$Stats=json_decode($rStats,true);
foreach($Stats as $k=>$v){
   echo $k.': '.$v.' download'.($v==1?'':'s');
}

答案 1 :(得分:0)

如果没有@ Shad在接受的答案中的帮助,我可能从未如此轻松地完成这件事。因此,我想在这里发布我的最终解决方案,几乎适用于所有人。这允许“直接链接”(即没有301/302或其他类型的重定向)正常运行(右键单击 - &gt;另存为也可以),同时仍然记录下载。请注意,这是相当“资源繁重”,一些共享主机可能会对使用类似的东西感到不安,但据我所知,这不应该是一个主要的消耗。我将托管的文件大小约为3-15MB,并且没有TON的下载量,所以在我的场景中我并不太担心这个,但是如果你使用这个解决方案,那就要非常了解这个事实!

<强>的download.php

<?php
$fileLookup = array(
            0=>'subdir/test.zip',
            1=>'another/sub/dir/test2.zip'
        );

$currentRelativeFileName = $fileLookup[$_GET['file']];
$currentFileName = basename($currentRelativeFileName);

$rawInfo=file_get_contents('stats.log');
$Info=json_decode($rawInfo,true);

if(isset($Info[$currentFileName])){
    $Info[$currentFileName]++;
}else{
    $Info[$currentFileName]=1;
}
$rawInfo=json_encode($Info);
$h=fopen('stats.log','c');// If $h is false, you couldn't open the file
flock($h,LOCK_EX);// lock the file
$b=fwrite($h,$rawInfo);// if $b is not greater than 0, nothing was written
flock($h,LOCK_UN);
fclose($h);

header("Content-type: application/octet-stream"); 
header("Content-disposition: attachment; filename=" . $currentFileName); 
readfile($currentRelativeFileName);

?>

<强> stats.php

<html>
<head>
    <title>Here are my stats!</title>
</head>
<body>
<?php
$rStats=file_get_contents('stats.log');
if (strlen($rStats) > 5){
    $Stats=json_decode($rStats,true);
    foreach($Stats as $k=>$v){
       echo $k.': '.$v.' download'.($v==1?'':'s') . '<br />';
    }
}else{
    echo 'No downloads';
}
?>
</body>