Download counter in PHP using .htaccess
Ever had this thought: “I want to fire something extra up when somebody downloads a certain file.”? This can be easily fixed by making all you download links link to a php page and output the download file for you. But what if the file is called directly in the browser, say http://www.gayadesign.com/scripts/photonav/photonav.zip? Apache will happily give the file to the user, without me noticing it. Luckily for us, .htaccess is a great place to mess around with Apache.
This article will explain how to make pre-download conditions in php using .htaccess. I’ll make a download counter in this one.
Download
Counter in PHP using .htaccess
Think of the possibilities! You could build a download counter, a place to check if the user has rights to download a certain file, create a bandwidth limit, and the list goes on and on.
Keeping track of downloads is a feature many developers want, even firing “something” (read: doStuff()) before a file is requested for download is handy.
Okay, what do you need?
- Apache web server with rewrite module enabled (probably the case)
- a decent text editor (like notepad++)
- optional: in this tutorial I’ll be using PHP
First, we need to get an .htaccess rule going. To do this you have to adjust your .htaccess file, or create a new one. To create a new .htaccess file in Notepad++ just open a new file and save as .htaccess. This is a hidden file on a unix system, but don’t worry.
Put the following lines in the .htaccess file:
#Let's do rewriting! RewriteEngine on RewriteRule ^(.*).(rar|zip|pdf)$ /download.php?file=$1.$2 [R,L]
This redirects every .rar, .zip and .pdf to the download.php file and include the file path as a parameter. I already hear developers think: ”And what if I prompted it to output a .php file though a browser call?”. We’ll fix that in the PHP file.
To add more extensions, separate them with a | (shift + \).
A few notes on .htaccess:
The file will work from the root of the folder you’ll put this into at your web server. All folders beneath the root will be affected. If you place the file in say /files/, the path will not be included in the file parameter. You’ll have to either add this in the download.php file or .htaccess file.
Upload the file in your webroot.
Next up, we are going to create a table in MySQL. You can do this in phpMyAdmin, it’s a small table.
If you already have a table called download, you have to change the SQL code.
CREATE TABLE `download` (
`filename` varchar(255) NOT NULL,
`stats` int(11) NOT NULL,
PRIMARY KEY (`filename`)
)
Execute this SQL statement in the SQL window, it’ll create a new table.
Now it’s time to get the PHP to work.
The following code allows you to keep track of download requests in the table you created above:
<?php
//put connection to database here
mysql_connect("localhost", "username", "password")
or die ("Sorry, can't connect to database.");
mysql_select_db("dbname");
$filename = mysql_real_escape_string($_GET['file']);
$path = $_SERVER['DOCUMENT_ROOT']."/"; //path of this file
$fullPath = $path.$filename; //path to download file
$filetypes = array("rar","zip","pdf");
if (!in_array(substr($filename, -3), $filetypes)) {
echo "Invalid download type.";
exit;
}
if ($fd = fopen ($fullPath, "r")) {
//add download stat
$result = mysql_query("SELECT COUNT(*) AS countfile FROM download
WHERE filename='" . $filename . "'");
$data = mysql_fetch_array($result);
$q = "";
if ($data['countfile'] > 0) {
$q = "UPDATE download SET stats = stats + 1 WHERE
filename = '" . $filename . "'";
} else {
$q = "INSERT INTO download (filename, stats) VALUES
('" . $filename . "', 1)";
}
$statresult = mysql_query($q);
//the next part outputs the file
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
header("Content-type: application/octet-stream");
header("Content-Disposition: filename="".$path_parts["basename"].""");
header("Content-length: $fsize");
header("Cache-control: private"); //use this to open files directly
while(!feof($fd)) {
$buffer = fread($fd, 2048);
echo $buffer;
}
}
fclose ($fd);
exit;
?>
Let me explain what you can change in the code in short; in the first part of the file, you’ll connect to your database. Please change the values to match your settings.
You can change the $filetypes to your likings, this will contain the accepted file extensions.
The php script will eventually output the file to your browser, neat eh? Download the zip file for a quick look in the files.
I hope this will help you to create pre-conditions on your downloads.
Good luck!
Articles like this one
10 Comments
-
THX!
I looking for long time this kind of script.Working very well!Great job!
-
Using .htaccess of this way has only rewrite-effect, and all other works are done by PHP. So that, when I read the title, I wondered why htaccess file can be used to delivered files? This post is the same as “PHP download manager”.
-
There are better ways to check a file extension. http://us2.php.net/pathinfo is one. It would be easy to sneak a file past your check.
-
First of all: thanks for all the comments!
@Tuan Anh
Maybe we interpret the title differently. I hope you still liked the article.@david
Isn’t that a better to check user uploaded files?
Because I uploaded the files on my server, I am sure I gave them the right extension.
Or what did you mean?
-
well ! The script is great , but i think .htaccess is difficult to use .
-
Thanks Adam. htaccess can be hard some times. So much possibilities, and a great chance to get a 500 error :(
-
Hey guys… I got it working but I wanted to add mp3, so I can track podcasts. But for some reason it doesnt work any ideas why?
Works fine with zip files.
-
Hey Rob,
Have you tried adding mp3 to the .htaccess and download.php file?
Good luck!
-
Great! Thank you!
…
Excellent :)
-
Well … actually one problem here is
Content-type: application/octet-stream
This is not working for my site, I would like to use the content-type that I entered in one of the Apache configuration files
and another small problem – the extension is not always 3 character (I removed that code completely)


Recent comments