1
Hi,
Man sieht ja oft auf Seiten Download-Counter in der Art, dass die Dateien heruntergeladen werden über Links in der Form "download.php?id=1234" oder ähnlich. Da mir das nicht besonders gefällt, stelle ich hier eine etwas andere Lösung vor.
Die Download-Dateien beliebigen Typs werden alle abgelegt im Ordner /downloads/, z.B.
Die Downloads werden erfasst in der MySQL-Tabelle "downloads":
Tabelle "downloads"
Im Ordner /php/tools/ liegt der Download-Counter "getfile.php". Dieses Skript zählt im Hintergrund die Downloads, indem es in die Tabelle "downloads" das Feld "counter" hochzählt, in dem das Feld "filename" den Wert des Dateinamens hat.
/php/tools/getfile.php
Ein include wird in dem Download-Skript benötigt, um den entsprechenden Mime-Type zu ermitteln, /php/tools/mimetypes.php:
In der .htaccess legen wir nun die Rule an, um den Download-Counter im Hintergrund laufen zu lassen. Ziel ist, den Download-Counter anzuwerfen, indem nun einfach ein Link auf die jeweilige Download-Datei gesetzt wird.
.htaccess
Wird nun eine Datei direkt angesprochen, z.B. über den Link
Man sieht ja oft auf Seiten Download-Counter in der Art, dass die Dateien heruntergeladen werden über Links in der Form "download.php?id=1234" oder ähnlich. Da mir das nicht besonders gefällt, stelle ich hier eine etwas andere Lösung vor.
Die Download-Dateien beliebigen Typs werden alle abgelegt im Ordner /downloads/, z.B.
/downloads/alle-meine-entchen.mp3
/downloads/silvester.doc
Die Downloads werden erfasst in der MySQL-Tabelle "downloads":
Tabelle "downloads"
----------------------------------------
| id | filename |counter|
----------------------------------------
| 1 | alle-meine-entchen.mp3 | 0 |
----------------------------------------
| 2 | silvester.doc | 0 |
---------------------------------------
Im Ordner /php/tools/ liegt der Download-Counter "getfile.php". Dieses Skript zählt im Hintergrund die Downloads, indem es in die Tabelle "downloads" das Feld "counter" hochzählt, in dem das Feld "filename" den Wert des Dateinamens hat.
/php/tools/getfile.php
<?php
define('DOWNLOADS_ROOT', '/var/www/public/domain.com/downloads/'); //absoluter Server-Pfad zum Downloads-Verzeichnis
require './mimetypes.php';
$filename = $_GET['filename'];
if (file_exists(DOWNLOADS_ROOT.$filename)) {
$conn = mysql_connect('server-name', 'benutzername', 'passwort') or die('Fehler bei der MySQL-Verbindung');
if (!mysql_select_db('datenbankname', $conn)) die('Fehler beim Wählen der Datenbank!');
mysql_query('UPDATE downloads SET counter=counter+1 WHERE filename=\''.mysql_real_escape_string($filename, $conn).'\'', $conn);
if (mysql_errno($conn)) die(mysql_error($conn));
mysql_close($conn);
header('Content-type: '.mime_type($filename));
header('Content-Disposition: attachment; filename="'.$filename.'"');
readfile(DOWNLOADS_ROOT.$filename);
}
?>
Ein include wird in dem Download-Skript benötigt, um den entsprechenden Mime-Type zu ermitteln, /php/tools/mimetypes.php:
<?php
//http://www.w3schools.com/media/media_mimeref.asp
function mime_type($filename) {
$extension = strtolower(substr(strrchr($filename, "."), 1));
switch($extension) {
case '323' : $mimetype = 'text/h323'; break;
case 'acx' : $mimetype = 'application/internet-property-stream'; break;
case 'ai' : $mimetype = 'application/postscript'; break;
case 'aif' : $mimetype = 'audio/x-aiff'; break;
case 'aifc' : $mimetype = 'audio/x-aiff'; break;
case 'aiff' : $mimetype = 'audio/x-aiff'; break;
case 'asf' : $mimetype = 'video/x-ms-asf'; break;
case 'asr' : $mimetype = 'video/x-ms-asf'; break;
case 'asx' : $mimetype = 'video/x-ms-asf'; break;
case 'au' : $mimetype = 'audio/basic'; break;
case 'avi' : $mimetype = 'video/x-msvideo'; break;
case 'axs' : $mimetype = 'application/olescript'; break;
case 'bas' : $mimetype = 'text/plain'; break;
case 'bcpio' : $mimetype = 'application/x-bcpio'; break;
case 'bin' : $mimetype = 'application/octet-stream'; break;
case 'bmp' : $mimetype = 'image/bmp'; break;
case 'c' : $mimetype = 'text/plain'; break;
case 'cat' : $mimetype = 'application/vnd.ms-pkiseccat'; break;
case 'cdf' : $mimetype = 'application/x-cdf'; break;
case 'cer' : $mimetype = 'application/x-x509-ca-cert'; break;
case 'class' : $mimetype = 'application/octet-stream'; break;
case 'clp' : $mimetype = 'application/x-msclip'; break;
case 'cmx' : $mimetype = 'image/x-cmx'; break;
case 'cod' : $mimetype = 'image/cis-cod'; break;
case 'cpio' : $mimetype = 'application/x-cpio'; break;
case 'crd' : $mimetype = 'application/x-mscardfile'; break;
case 'crl' : $mimetype = 'application/pkix-crl'; break;
case 'crt' : $mimetype = 'application/x-x509-ca-cert'; break;
case 'csh' : $mimetype = 'application/x-csh'; break;
case 'css' : $mimetype = 'text/css'; break;
case 'dcr' : $mimetype = 'application/x-director'; break;
case 'der' : $mimetype = 'application/x-x509-ca-cert'; break;
case 'dir' : $mimetype = 'application/x-director'; break;
case 'dll' : $mimetype = 'application/x-msdownload'; break;
case 'dms' : $mimetype = 'application/octet-stream'; break;
case 'doc' : $mimetype = 'application/msword'; break;
case 'dot' : $mimetype = 'application/msword'; break;
case 'dvi' : $mimetype = 'application/x-dvi'; break;
case 'dxr' : $mimetype = 'application/x-director'; break;
case 'eps' : $mimetype = 'application/postscript'; break;
case 'etx' : $mimetype = 'text/x-setext'; break;
case 'evy' : $mimetype = 'application/envoy'; break;
case 'exe' : $mimetype = 'application/octet-stream'; break;
case 'fif' : $mimetype = 'application/fractals'; break;
case 'flr' : $mimetype = 'x-world/x-vrml'; break;
case 'gif' : $mimetype = 'image/gif'; break;
case 'gtar' : $mimetype = 'application/x-gtar'; break;
case 'gz' : $mimetype = 'application/x-gzip'; break;
case 'h' : $mimetype = 'text/plain'; break;
case 'hdf' : $mimetype = 'application/x-hdf'; break;
case 'hlp' : $mimetype = 'application/winhlp'; break;
case 'hqx' : $mimetype = 'application/mac-binhex40'; break;
case 'hta' : $mimetype = 'application/hta'; break;
case 'htc' : $mimetype = 'text/x-component'; break;
case 'htm' : $mimetype = 'text/html'; break;
case 'html' : $mimetype = 'text/html'; break;
case 'htt' : $mimetype = 'text/webviewhtml'; break;
case 'ico' : $mimetype = 'image/x-icon'; break;
case 'ief' : $mimetype = 'image/ief'; break;
case 'iii' : $mimetype = 'application/x-iphone'; break;
case 'ins' : $mimetype = 'application/x-internet-signup'; break;
case 'isp' : $mimetype = 'application/x-internet-signup'; break;
case 'jfif' : $mimetype = 'image/pipeg'; break;
case 'jpe' : $mimetype = 'image/jpeg'; break;
case 'jpeg' : $mimetype = 'image/jpeg'; break;
case 'jpg' : $mimetype = 'image/jpeg'; break;
case 'js' : $mimetype = 'application/x-javascript'; break;
case 'latex' : $mimetype = 'application/x-latex'; break;
case 'lha' : $mimetype = 'application/octet-stream'; break;
case 'lsf' : $mimetype = 'video/x-la-asf'; break;
case 'lsx' : $mimetype = 'video/x-la-asf'; break;
case 'lzh' : $mimetype = 'application/octet-stream'; break;
case 'm13' : $mimetype = 'application/x-msmediaview'; break;
case 'm14' : $mimetype = 'application/x-msmediaview'; break;
case 'm3u' : $mimetype = 'audio/x-mpegurl'; break;
case 'man' : $mimetype = 'application/x-troff-man'; break;
case 'mdb' : $mimetype = 'application/x-msaccess'; break;
case 'me' : $mimetype = 'application/x-troff-me'; break;
case 'mht' : $mimetype = 'message/rfc822'; break;
case 'mhtml' : $mimetype = 'message/rfc822'; break;
case 'mid' : $mimetype = 'audio/mid'; break;
case 'mny' : $mimetype = 'application/x-msmoney'; break;
case 'mov' : $mimetype = 'video/quicktime'; break;
case 'movie' : $mimetype = 'video/x-sgi-movie'; break;
case 'mp2' : $mimetype = 'video/mpeg'; break;
case 'mp3' : $mimetype = 'audio/mpeg'; break;
case 'mpa' : $mimetype = 'video/mpeg'; break;
case 'mpe' : $mimetype = 'video/mpeg'; break;
case 'mpeg' : $mimetype = 'video/mpeg'; break;
case 'mpg' : $mimetype = 'video/mpeg'; break;
case 'mpp' : $mimetype = 'application/vnd.ms-project'; break;
case 'mpv2' : $mimetype = 'video/mpeg'; break;
case 'ms' : $mimetype = 'application/x-troff-ms'; break;
case 'mvb' : $mimetype = 'application/x-msmediaview'; break;
case 'nws' : $mimetype = 'message/rfc822'; break;
case 'oda' : $mimetype = 'application/oda'; break;
case 'p10' : $mimetype = 'application/pkcs10'; break;
case 'p12' : $mimetype = 'application/x-pkcs12'; break;
case 'p7b' : $mimetype = 'application/x-pkcs7-certificates'; break;
case 'p7c' : $mimetype = 'application/x-pkcs7-mime'; break;
case 'p7m' : $mimetype = 'application/x-pkcs7-mime'; break;
case 'p7r' : $mimetype = 'application/x-pkcs7-certreqresp'; break;
case 'p7s' : $mimetype = 'application/x-pkcs7-signature'; break;
case 'pbm' : $mimetype = 'image/x-portable-bitmap'; break;
case 'pdf' : $mimetype = 'application/pdf'; break;
case 'pfx' : $mimetype = 'application/x-pkcs12'; break;
case 'pgm' : $mimetype = 'image/x-portable-graymap'; break;
case 'pko' : $mimetype = 'application/ynd.ms-pkipko'; break;
case 'pma' : $mimetype = 'application/x-perfmon'; break;
case 'pmc' : $mimetype = 'application/x-perfmon'; break;
case 'pml' : $mimetype = 'application/x-perfmon'; break;
case 'pmr' : $mimetype = 'application/x-perfmon'; break;
case 'pmw' : $mimetype = 'application/x-perfmon'; break;
case 'pnm' : $mimetype = 'image/x-portable-anymap'; break;
case 'pot,' : $mimetype = 'application/vnd.ms-powerpoint'; break;
case 'ppm' : $mimetype = 'image/x-portable-pixmap'; break;
case 'pps' : $mimetype = 'application/vnd.ms-powerpoint'; break;
case 'ppt' : $mimetype = 'application/vnd.ms-powerpoint'; break;
case 'prf' : $mimetype = 'application/pics-rules'; break;
case 'ps' : $mimetype = 'application/postscript'; break;
case 'pub' : $mimetype = 'application/x-mspublisher'; break;
case 'qt' : $mimetype = 'video/quicktime'; break;
case 'ra' : $mimetype = 'audio/x-pn-realaudio'; break;
case 'ram' : $mimetype = 'audio/x-pn-realaudio'; break;
case 'ras' : $mimetype = 'image/x-cmu-raster'; break;
case 'rgb' : $mimetype = 'image/x-rgb'; break;
case 'rmi' : $mimetype = 'audio/mid'; break;
case 'roff' : $mimetype = 'application/x-troff'; break;
case 'rtf' : $mimetype = 'application/rtf'; break;
case 'rtx' : $mimetype = 'text/richtext'; break;
case 'scd' : $mimetype = 'application/x-msschedule'; break;
case 'sct' : $mimetype = 'text/scriptlet'; break;
case 'setpay' : $mimetype = 'application/set-payment-initiation'; break;
case 'setreg' : $mimetype = 'application/set-registration-initiation'; break;
case 'sh' : $mimetype = 'application/x-sh'; break;
case 'shar' : $mimetype = 'application/x-shar'; break;
case 'sit' : $mimetype = 'application/x-stuffit'; break;
case 'snd' : $mimetype = 'audio/basic'; break;
case 'spc' : $mimetype = 'application/x-pkcs7-certificates'; break;
case 'spl' : $mimetype = 'application/futuresplash'; break;
case 'src' : $mimetype = 'application/x-wais-source'; break;
case 'sst' : $mimetype = 'application/vnd.ms-pkicertstore'; break;
case 'stl' : $mimetype = 'application/vnd.ms-pkistl'; break;
case 'stm' : $mimetype = 'text/html'; break;
case 'sv4cpio': $mimetype = 'application/x-sv4cpio'; break;
case 'sv4crc' : $mimetype = 'application/x-sv4crc'; break;
case 'svg' : $mimetype = 'image/svg+xml'; break;
case 'swf' : $mimetype = 'application/x-shockwave-flash'; break;
case 't' : $mimetype = 'application/x-troff'; break;
case 'tar' : $mimetype = 'application/x-tar'; break;
case 'tcl' : $mimetype = 'application/x-tcl'; break;
case 'tex' : $mimetype = 'application/x-tex'; break;
case 'texi' : $mimetype = 'application/x-texinfo'; break;
case 'texinfo': $mimetype = 'application/x-texinfo'; break;
case 'tgz' : $mimetype = 'application/x-compressed'; break;
case 'tif' : $mimetype = 'image/tiff'; break;
case 'tiff' : $mimetype = 'image/tiff'; break;
case 'tr' : $mimetype = 'application/x-troff'; break;
case 'trm' : $mimetype = 'application/x-msterminal'; break;
case 'tsv' : $mimetype = 'text/tab-separated-values'; break;
case 'txt' : $mimetype = 'text/plain'; break;
case 'uls' : $mimetype = 'text/iuls'; break;
case 'ustar' : $mimetype = 'application/x-ustar'; break;
case 'vcf' : $mimetype = 'text/x-vcard'; break;
case 'vrml' : $mimetype = 'x-world/x-vrml'; break;
case 'wav' : $mimetype = 'audio/x-wav'; break;
case 'wcm' : $mimetype = 'application/vnd.ms-works'; break;
case 'wdb' : $mimetype = 'application/vnd.ms-works'; break;
case 'wks' : $mimetype = 'application/vnd.ms-works'; break;
case 'wmf' : $mimetype = 'application/x-msmetafile'; break;
case 'wps' : $mimetype = 'application/vnd.ms-works'; break;
case 'wri' : $mimetype = 'application/x-mswrite'; break;
case 'wrl' : $mimetype = 'x-world/x-vrml'; break;
case 'wrz' : $mimetype = 'x-world/x-vrml'; break;
case 'xaf' : $mimetype = 'x-world/x-vrml'; break;
case 'xbm' : $mimetype = 'image/x-xbitmap'; break;
case 'xla' : $mimetype = 'application/vnd.ms-excel'; break;
case 'xlc' : $mimetype = 'application/vnd.ms-excel'; break;
case 'xlm' : $mimetype = 'application/vnd.ms-excel'; break;
case 'xls' : $mimetype = 'application/vnd.ms-excel'; break;
case 'xlt' : $mimetype = 'application/vnd.ms-excel'; break;
case 'xlw' : $mimetype = 'application/vnd.ms-excel'; break;
case 'xof' : $mimetype = 'x-world/x-vrml'; break;
case 'xpm' : $mimetype = 'image/x-xpixmap'; break;
case 'xwd' : $mimetype = 'image/x-xwindowdump'; break;
case 'z' : $mimetype = 'application/x-compress'; break;
case 'zip' : $mimetype = 'application/zip'; break;
default : $mimetype = 'application/octet-stream'; break;
}
return $mimetype;
}
?>
In der .htaccess legen wir nun die Rule an, um den Download-Counter im Hintergrund laufen zu lassen. Ziel ist, den Download-Counter anzuwerfen, indem nun einfach ein Link auf die jeweilige Download-Datei gesetzt wird.
.htaccess
RewriteEngine On
RewriteRule ^downloads/([A-Za-z0-9\-_]+\.[A-Za-z0-9]+)$ ./php/tools/getfile.php?filename=$1
Wird nun eine Datei direkt angesprochen, z.B. über den Link
<a href="/downloads/alle-meine-entchen.mp3" alt="Alle meine Entchen">Download</a>
wird, von außen nicht ersichtlich, der Download-Counter angesprochen, Counter aufgezählt und der Dateidownload erzwungen (also die Anzeige im Browser, auch für Bilddateien etc., unterbunden [Content-Disposition: attachment]). Das Feld "counter" kann irgendwo ausgelesen werden um die Anzahl der Downloads für die erfassten Dateien anzuzeigen.