tracking download counts
Moderator: General Moderators
-
permutations
- Forum Commoner
- Posts: 52
- Joined: Sat Dec 07, 2002 11:45 am
tracking download counts
I want to track how many times people download a zip file that's on my site. Right now I'm counting the number of times that people click the "Download now" button, but the download could be cancelled so this isn't completely accurate. In the daily Webalizer statistics, there's a count for the number of accesses to this zip file. Is there a way to obtain this in real time (versus analyzing the daily server statistics)? What's the best way to track download counts?
you could have the classic download script.
make a script called download.php which takes a GET variable containing the file to download. This script simply has to passthru the file and add one to the dowload count.
This means that all your links "somefile.zip" become "download.php?f=somefile.zip"
This way you may be able to use the php function connection_abort ( iirc ) that tells you if the user jumped ship
make a script called download.php which takes a GET variable containing the file to download. This script simply has to passthru the file and add one to the dowload count.
This means that all your links "somefile.zip" become "download.php?f=somefile.zip"
This way you may be able to use the php function connection_abort ( iirc ) that tells you if the user jumped ship
-
permutations
- Forum Commoner
- Posts: 52
- Joined: Sat Dec 07, 2002 11:45 am
maybe something like this for your download.php
to check if the download was complete ( after a brief look at this page http://www.php.net/manual/en/features.c ... ndling.php ) i think you need to register a shutdown function ( register_shutdown_function() ) and inside that function check the value of the function connection_aborted(). This will return true if the connection was aborted. To count only files that have been fully downloaded put the code to add one to your counters inside the shutdown function and only run it if connection_aborted()!=true;
Code: Select all
<?
$fileDir='/path/to/downloadable/files/';
$fileName=$_GET['file'];
$completeFilePath=$fileDir.'/'.$fileName;
header('Cache-Control: no-cache, must-revalidate');
header('Pragma: no-cache');
header("Content-type: application/octet-stream\nContent-Disposition: inline; filename="".$fileName.""\nContent-length: ".(string)(filesize($completeFilePath)));
$fd=fopen($completeFilePath,'r');
fpassthru($fd);
// add one to your file download counters here
?>-
permutations
- Forum Commoner
- Posts: 52
- Joined: Sat Dec 07, 2002 11:45 am
Looking at the message three-up about "classic download script" a little more, I realize that's what I'm already doing. The problem with this approach is that it counts clicks on the download button, but there's no way to tell if the file was really downloaded. I'll have to read up on that connection_aborted() function. I hadn't heard of that.
What do these header commands do:
header('Cache-Control: no-cache, must-revalidate');
header('Pragma: no-cache');
header("Content-type: application/octet-stream\nContent-Disposition: inline;
Also, what is the reason for obtaining a file pointer and calling fpassthru? What does that accomplish?
What do these header commands do:
header('Cache-Control: no-cache, must-revalidate');
header('Pragma: no-cache');
header("Content-type: application/octet-stream\nContent-Disposition: inline;
Also, what is the reason for obtaining a file pointer and calling fpassthru? What does that accomplish?
Last edited by permutations on Thu Apr 03, 2003 8:55 am, edited 1 time in total.
I think he's pointing you toward something like this, assuming you keep a count of all downloads on a text file:
Link to file: http://www.yourdomain.com/download.php?file=filename
Understand that the above is an outline of what I think will work, and isn't yet tested. Also note that you don't have to use a text file to do the count, nor do you have to do an enmasse count for all files downloaded. You can set it up to count only the downloads of each particluar file.
Hope this helps!
Link to file: http://www.yourdomain.com/download.php?file=filename
Code: Select all
<?
/***** Download.php *****/
//First, set the file variable properly. File = name of file in string
$file = $_GET['file'];
if($file) {
//Check to see if that file exists
if(file_exists("/link/to/downloads/$file") == false) {
die("This file does not exist!")
} else {
//Open text file containing download count
$file = 'count.php';
$open = fopen($file , 'r');
$count = fread($handle , filesize($file));
fclose($open);
//Add one to the count
$newcount = $count+1;
//Open count file and write new count to it
$file = 'count.php';
$count = $newcount;
$open = fopen($file , 'w');
fwrite($open , $count);
fclose($open);
}
}
?>Hope this helps!
>What do these header commands do:
>header('Cache-Control: no-cache, must-revalidate');
>header('Pragma: no-cache');
>header("Content-type: application/octet-stream\nContent-Disposition: inline;
To be honest i ripped the downbload script from fpassthru. these headers force the download box to be displayed.
>Also, what is the reason for obtaining a file pointer and calling fpassthru? >What does that accomplish?
I thought to use it so you can actually see if the download has finished. If you just point them at a file ( eg somefile.zip ) then how can you tell they have finished the download? You cant with connection_aborted as its not a php script!
This soloution uses the php script to pass the file thru php just like you would send html normally ( altho the headers let the browser knwo its a download ). Also because of the "power" of php we can detect an aborted connection ( unlike just our regular somefile.zip ).
Providing just a link to somefile.zip means that your power of control stops as soon as they click the link. The passthru method gives you control to the very end *grin*
>header('Cache-Control: no-cache, must-revalidate');
>header('Pragma: no-cache');
>header("Content-type: application/octet-stream\nContent-Disposition: inline;
To be honest i ripped the downbload script from fpassthru. these headers force the download box to be displayed.
>Also, what is the reason for obtaining a file pointer and calling fpassthru? >What does that accomplish?
I thought to use it so you can actually see if the download has finished. If you just point them at a file ( eg somefile.zip ) then how can you tell they have finished the download? You cant with connection_aborted as its not a php script!
This soloution uses the php script to pass the file thru php just like you would send html normally ( altho the headers let the browser knwo its a download ). Also because of the "power" of php we can detect an aborted connection ( unlike just our regular somefile.zip ).
Providing just a link to somefile.zip means that your power of control stops as soon as they click the link. The passthru method gives you control to the very end *grin*
-
permutations
- Forum Commoner
- Posts: 52
- Joined: Sat Dec 07, 2002 11:45 am
Sorry to be dense, but what do you mean you "ripped the download script from fpassthru". Is "fpassthru" a place in this context? Where did you see the script?
I'm still not understanding how using fpassthru to read the file can tell me whether the user has completed the download. I read the description of fpassthru, and it seems to just return the number of bytes in the file. What can I do with this? How does it tell me when the download has finished?
By the way, I store the download count in a MySQL database, rather than a text file.
... Oh wait, I think you mean the user notes on the fpassthru page of the php.net manual, yes? I see reference to it there. I need to understand what these lines do. Manual time...
I'm still not understanding how using fpassthru to read the file can tell me whether the user has completed the download. I read the description of fpassthru, and it seems to just return the number of bytes in the file. What can I do with this? How does it tell me when the download has finished?
By the way, I store the download count in a MySQL database, rather than a text file.
... Oh wait, I think you mean the user notes on the fpassthru page of the php.net manual, yes? I see reference to it there. I need to understand what these lines do. Manual time...
I think those headers simply keep the page from caching information that might be important in keeping the count on the download page correct.
Look at my solution and see if it makes any sense to you. I'm not sure whether or not I have something there, but I must admit I'm very interested in seeing exactly what that code might do.
I wish I weren't at school right now, or I'd do some testing on my computer
Look at my solution and see if it makes any sense to you. I'm not sure whether or not I have something there, but I must admit I'm very interested in seeing exactly what that code might do.
I wish I weren't at school right now, or I'd do some testing on my computer
-
permutations
- Forum Commoner
- Posts: 52
- Joined: Sat Dec 07, 2002 11:45 am
Good grief, this was a pain in the neck--mainly because of IE, which requires special handling. But I did find a working solution. Here it is:
One other comment... fpassthru() loads the entire file into memory, which can be a problem for large files. In that case, it's best to replace fpassthru with this:
I tested all this and it works perfectly in all the browsers I tested (IE6, Netscape 4, Mozilla aka Netscape 7).
Code: Select all
<?php
$fileDir = '/home/mydir/public_html/files/';
$fileName = 'myfile.zip';
$completeFilePath=$fileDir.$fileName;
// IE cannot download without a cache, so clear these headers
if(strpos($HTTP_SERVER_VARSї'HTTP_USER_AGENT'], 'MSIE')){
header("Pragma: ");
header("Cache-Control: ");
}
else { //prevent caching
header('Pragma: no-cache');
header('Cache-Control: no-cache, must-revalidate');
}
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=".$fileName);
header("Content-Length: ".filesize("$completeFilePath"));
$fn=fopen($completeFilePath,'rb');
fpassthru($fn);
require_once('Connections/conMyDB.php');
mysql_select_db($database_conMyDB, $conMyDB);
// increase download count
$query = "UPDATE utilities SET DLCount=(DLCount+1) WHERE UtilityID = $UtilityID";
$rs = mysql_query($query, $conMyDB);
?>Code: Select all
while(!feof($fn)) { // this replacement for fpassthru uses less memory (for large files)
$buffer = fread($fn, 4096);
print $buffer;
}yey youve got it!
now to detect broken downloads you can do something like this i think:
im not 100% sure it will work but from what i understand of register_shutdown_fnuction,connection_aborted and fpassthru it should be
now to detect broken downloads you can do something like this i think:
Code: Select all
function onshutdown() {
if (connection_aborted()) {
// the download was aborted so dont add one to the download
} else {
// the download was ok so add one to the download count
}
}
register_shutdown_function(onShutdown);-
permutations
- Forum Commoner
- Posts: 52
- Joined: Sat Dec 07, 2002 11:45 am