'versteckter' Downloadzähler

Hi, warum sollte man sich (und vor allem der Datenbank) mehr Arbeit machen als nötig? Warum zwei Queries, wenn doch eins vollkommen ausreicht:
PHP:
mysql_query("UPDATE `tabellenname` SET `anzahl_downloads` = `anzahl_downloads` + 1 WHERE `id` = '" . mysql_real_escape_string($lied_id) . "'");

Die mod_rewirte Geschichte funktioniert im Prinzip folgendermasse:

1. Du erstellst eine Datei namens ".htacces", und schreibst ungefähr folgenden Inhalt hinein:
Code:
RewriteEngine On

RewriteRule ^download/lied([0-9]+)\.mp3$ index.php?lied=$1 [L,QSA]
Diese Einstellungen leiten alle Zugriffe auf die URL download/lied#.mp3 (wobei # für eine beliebige ganze Zahl steht) weiter auf das Script downloads.php

2. In der Datei index.php kann nun mittel $_GET['lied'] auf die Nummer des gewünschten Lieds zugreifen. Diese also für den Downloadcounter (entspricht $lied_id) verwenden und anschliessend entweder auf das Lied weiterleiten, oder die Datei öffnen und den Inhalt schicken. Letzteres funktioniert in etwa so:
PHP:
$file = 'lied' . $lied_id . '.mp3';

readfile($file);

3. Aus Gründen der Sicherheit UNBEDINGT! den Inhalt der Variablen $_GET['lied'] überprüfen, da deine Website sonst sehr leicht gehackt werden kann.

Ich hoffe das hilft erstmal weiter.

Ich hätte aber gerne dass der der die Datei herunterläd garnichts davon mitbekommt. :)

gruß
crix


edit:
Irgendwie sieht das mir soo kompliziert aus. Um Missverständnisse aus der Welt zu schaffen erläutere ich lieber nochmal was ich haben möchte.

Ich möchte nur 2 Seiten (Dateien). Die Datei index.php in der man die Datei runterladen kann (am besten mit dem Link "bandname - lied.mp3", damit das beliebte "Rechtsklick -> Speichern unter.." auch möglich ist, wobei es besser wäre dass die Datei immer Lokal auf dem PC zur Wiedergabe gespeichert werden muss) und die Datei downloads.php (wie ein paar Zeilen weiter oben) in der ich die Downloadanzahl sehen kann.
Und es ist nur eine Datei deren Downloads gezählt werden sollen, es kommt auch keine dazu.

Dies ist jetzt nicht negativ gemeint. Und vielleicht ist das doch so kompliziert.. und ihr habt es richtig verstanden. Ich wollte es nur noch einmal erläutern, dass keine Missverständnisse auftreten.
 
Zuletzt bearbeitet:
Okay, ich habe jetzt eine Idee :P mit dem wir die index.html garnicht erst anfassen.. der Download-Link führt zur Datei download.php.. und diese Datei soll einen Download in die MySQL-Tabelle (meinetwegen auch in ein Textdokument) hinzuzählen, ein "Danke." mittig ausgeben wie in dem unteren Code.. und gleichzeitig bzw. sofort das Fenster öffnen wo die Datei gespeichert werden soll..

Danke-Seite
HTML:
<html>
<head>
<title>Danke.</title>
<style type="text/css">
<!--
body,td,th {
    font-family: Verdana, Arial, Helvetica, sans-serif;
    font-size: 10px;
    color: #000000;
}
body {
    background-color: #000000;
    margin-left: 0px;
    margin-top: 0px;
    margin-right: 0px;
    margin-bottom: 0px;
}
.Stil1 {color: #FFFFFF}
-->
</style>
<head>
</head>
<body>
<table width="100%" height="100%" border="0" align="center" cellpadding="0" cellspacing="0">
  <!--DWLayoutTable-->
  <tr>
    <td width="100%" height="100%" align="center" valign="middle"><span class="Stil1">Danke.</span></td>
  </tr>
</table>
</body>
</html>

Dann soll es ein php-Dokument geben, nennen wir es Downloadausgabe in dem die Downloadmenge ausgegeben wird.. also wie oft das Lied heruntergeladen wurde..

Downloadausgabe-Seite
HTML:
<html>
<head>
<title>Der Remix wurde <?php echo $anzahl_downloads ?> mal runtergeladen.</title>
<style type="text/css">
<!--
body,td,th {
    font-family: Verdana, Arial, Helvetica, sans-serif;
    font-size: 10px;
    color: #000000;
}
body {
    background-color: #000000;
    margin-left: 0px;
    margin-top: 0px;
    margin-right: 0px;
    margin-bottom: 0px;
}
.Stil1 {color: #FFFFFF}
-->
</style>
<head>
</head>
<body>
<table width="100%" height="100%" border="0" align="center" cellpadding="0" cellspacing="0">
  <!--DWLayoutTable-->
  <tr>
    <td width="100%" height="100%" align="center" valign="middle"><span class="Stil1">Der Remix wurde <?php echo $anzahl_downloads ?> mal runtergeladen.</span></td>
  </tr>
</table>
</body>
</html>

Wäre dies einfacher?

crix
 
Ich hab da mal was vorbereitet :-)
... vielleicht erkennst du dann besser, wie einfach es gemeint ist und dass es recht simpel ist :)

.htaccess
Code:
RewriteEngine On
RewriteCond    %{SCRIPT_FILENAME}  -f 
RewriteRule   \.mp3$  download.php
In der 2. Zeile wird geprüft, ob die Datei überhaupt existiert, in der 3.Zeile alle Anfragen auf Dateien mit Endung mp3 auf die download.php umgeschrieben

download.php
PHP:
<?php
$server   = "localhost";  
$db       = "datenbank"; 
$user     = "user";       
$passwort = "pwd"; 

mysql_connect($server,$user,$passwort) 
  or die("Error:Connection");
  
mysql_select_db($db)
  or die("Error:DB");



  //wenn download.php nicht direkt aufgerufen wurde
if($_SERVER['SCRIPT_NAME'] != $_SERVER['REQUEST_URI'])
  {
      
    if(
        basename($_SERVER['SCRIPT_NAME'])=='download.php' 
              && 
        preg_match('@\.mp3$@',$_SERVER['REQUEST_URI'])
      )
      {//Es wird gedownloadet, Counter inkrementieren und mp3 ausgeben    
          
          //Download zählen
        mysql_query('UPDATE `tabellenname` 
                      SET `anzahl_downloads` = `anzahl_downloads`+1 
                        WHERE `file` = "'.mysql_real_escape_string(basename($_SERVER['REQUEST_URI'])).'"'
                   )
        or die('ERROR:UPDATE');
                   
          //Sollte das mp3 noch nicht in der DB stehen, wird der entsprechende Datensatz angelegt
        if(!mysql_affected_rows())
          {
            mysql_query('INSERT INTO `tabellenname` 
                            SET `anzahl_downloads` = 1,
                            `file` = "'.mysql_real_escape_string(basename($_SERVER['REQUEST_URI'])).'"'
                   )
           or die('ERROR:INSERT');
          }
      
          //Header und Ausgabe
        header('Content-Type:audio/x-mpeg');
        readfile($_SERVER['REQUEST_URI']);
      }
    else
      {
        
        /**
          * Funktion zur Rückgabe der counts
          * Argument:
          * die id(steht im Feld id)
          * oder  
          * den Dateinamen(steht im Feld file)
          ***/
        
        function counter($arg)
        {
          $field=(is_numeric($arg))?'`id`':'`file`';
          
          $sql=mysql_query('SELECT `anzahl_downloads` 
                              FROM `tabellenname` 
                                WHERE '.$field.' = "'.mysql_real_escape_string($arg).'"')
              or die('ERROR:SELECT');
          
          return (@mysql_result($sql,0)*1);
        }
      }
    
  }

?>

Erläuterungen stehen ja soweit drinnen.
Du musst natürlich die Zugangsdaten anpassen.
Der Tabellenname ist tabellenname
Die Tabelle benötigt 3 Spalten:
  1. id(die numerischeID)
  2. file(hier kommt der Dateiname herein, müsste also varchar o.ä. sein)
  3. anzahl_downloads(die Downloads)

Das wars eigentlich schon.

Du kannst die download.php nun in andere PHP-Skripte includen, wenn du das tust, hast du die Funktion counter() verfügbar.
Dieser kannst du als Argument die ID des mp3s übergeben, aber auch einfach den Dateinamen...sie gibt dir die Anzahl der dazugehörigen Downloads zurück.

Du selbst musst in der Tabelle keine Datensätze anlegen, dies macht die download.php von selbst, sobald eine Datei das erste mal heruntergeladen wird.

Falls es also doch mal mehr als 1 mp3 werden, einfach hochladen und fertig :)

index.php zum Testen, ob der Zähler funktioniert:
PHP:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<meta name="author"             content="doktormolle">
<meta name="date"               content="2008-10-31">
<title>Downloadcounter</title>
</head>
<body>

<table border="1">
  <tr><th>File</th><th>Downloads</th></tr>  
<?php
require('download.php');

if ($handle = opendir('.')) 
{
  while (false !== ($file = readdir($handle))) 
    {
      if (preg_match('@\.mp3$@',$file)) 
        {
          echo '<tr><td><a href="'.$file.'">'.$file.'</a></td><td>'.counter($file).'</td></tr>';
        }
    }
    closedir($handle);
}
?> 
</table>
</body>
</html>
 

Anhänge

Erläuterungen stehen ja soweit drinnen.
Du musst natürlich die Zugangsdaten anpassen.
Der Tabellenname ist tabellenname
Die Tabelle benötigt 3 Spalten:
  1. id(die numerischeID)
  2. file(hier kommt der Dateiname herein, müsste also varchar o.ä. sein)
  3. anzahl_downloads(die Downloads)

Hm.. cool.. soweit hab das sogar ICH gecheckt :)

nur eine Frage (im Moment) ist noch offen zu der Tabelle.. was für eine "Länge/Set1" sollte ich bei den einzelnen Spalten wählen? Und was für ein Typ jeweils, bei file VARCHAR, soweit bin ich schon :) aber den rest verstehe ich eigentlich gut :) da kann man echt was lernen bei.. Vielen Dank!!

crix
 
Mit:
id=>tinyint
file=>varchar(64)
anzahl_downloads=>smallint

solltest du erstmal sicher sein vor Problemen.
  • varchar(64) erlaubt bis zu 64 Zeichen im zu speichernden Dateinamen(du kannst da auch einen anderen Wert eintragen bis maximal 255)
  • tinyint ermöglicht bis zu 255 verschiedene Dateien
  • smallint ermöglicht das Zählen von bis zu 65535 Downloads(pro Datei)

Bei smallint und tinyint wähle zusätzlich die Option UNSIGNED
Unsigned bedeutet, es können keine Werte mit Vorzeichen gespeichert werden...brauchst du ja auch nicht(wenn du UNSIGNED bei den INT-Feldern weglässt, halbieren sich dort die von mir gennanten Werte)
 
Mit:
id=>tinyint
file=>varchar(64)
anzahl_downloads=>smallint

solltest du erstmal sicher sein vor Problemen.
  • varchar(64) erlaubt bis zu 64 Zeichen im zu speichernden Dateinamen(du kannst da auch einen anderen Wert eintragen bis maximal 255)
  • tinyint ermöglicht bis zu 255 verschiedene Dateien
  • smallint ermöglicht das Zählen von bis zu 65535 Downloads(pro Datei)

Bei smallint und tinyint wähle zusätzlich die Option UNSIGNED
Unsigned bedeutet, es können keine Werte mit Vorzeichen gespeichert werden...brauchst du ja auch nicht(wenn du UNSIGNED bei den INT-Feldern weglässt, halbieren sich dort die von mir gennanten Werte)

Danke dir!! Also so ists dann richtig?
gruß
 

Anhänge

  • mysql.jpg
    mysql.jpg
    71,6 KB · Aufrufe: 16
Jo :)

id könnte als Extra noch ein auto_increment vertragen.

hm.. geht irgendwie nicht :( ist das schlimm?

crix


edit: Habe es jetzt mal testen wollen, doch eine Frage bleibt mir noch offen.. Wie binde ich das Ganze in meine index.html o. index.php ein?

HTML:
<html>
<head>
<title>Titel</title>
<style type="text/css">
<!--
body {
background:#000 url(bg.png) no-repeat center top;
}
div#flash {
width:588px;
height:250px;
position:absolute;
left:50%;
top:50%;
margin-left:-294px;
margin-top:-125px;
}
div#image {
width:525px;
height:200px;
position:absolute;
right:0;
top:50%;
margin-top:125px;
}
-->
</style>

</head>
<body>

<div id="flash">
     <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,28,0" width="588" height="250">
             <param name="movie" value="video.swf">
             <param name="quality" value="high">
             <param name="BGCOLOR" value="#FFFFFF">
             <embed src="video.swf" width="588" height="250" quality="high" pluginspage="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash" type="application/x-shockwave-flash" bgcolor="#FFFFFF"></embed>
     </object>
</div>
<div id="image">
     <img src="download.png" alt="" width="525" height="200" border="0" usemap="#Map">
<map name="Map">
  <area shape="poly" coords="15,42,108,19,120,44,27,69" href="Interpret_-_Lied_(Exclusivdownload).mp3" alt="downloaden">
</map>
</div>
</body>
</html>
 
Zuletzt bearbeitet:
hm.. geht irgendwie nicht :( ist das schlimm?
Nicht zwangsläufig, aber auf jeden Fall merkwürdig.

Hast du denn schon einen PRIMARY KEY angelegt?


Zu dem anderen:

Kommt drauf an, was du tun willst...wenn du die Anzahl der Downloads ausgeben willst, binde die download.php ein per require() oder include().
Dort, wo du dann die entsprechende Zahl usgeben willst, notiere:
Code:
<?php echo counter('Interpret_-_Lied_(Exclusivdownload).mp3');?>
 
Nicht zwangsläufig, aber auf jeden Fall merkwürdig.

Hast du denn schon einen PRIMARY KEY angelegt?


Zu dem anderen:

Kommt drauf an, was du tun willst...wenn du die Anzahl der Downloads ausgeben willst, binde die download.php ein per require() oder include().
Dort, wo du dann die entsprechende Zahl usgeben willst, notiere:
Code:
<?php echo counter('Interpret_-_Lied_(Exclusivdownload).mp3');?>

Nein habe ich noch nicht angelegt. Ich meine was muss ich machen dass der Download (der in index.html steht, also Interpret_-_Lied_(Exclusivdownload).mp3) auch gezählt wird?

crix
 
Zurück