Jump to content

Logging successful file downloads


VirtualOdin

Recommended Posts

So, I have a script that works downloading a file - excerpt below:

 

header("Pragma: public"); 
header("Expires: 0");
header('Content-type: "application/octet-stream"');
header("Cache-Control: private",false); 
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
$f = "Content-Disposition: attachment; filename=\"".$myfile['downloadname'].".".$myfile['ext']."\""; 
header($f);
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($file));
    ob_clean();
    flush();
readfile("$file");
exit();

 

I record elsewhere in a mysql database when the script is started.

 

In addition, I'd like to be able to record whether the download completes (successfully or otherwise). 

 

As it is, the script can run and the user press cancel and it looks like a download but isn't.

 

Is this possible?  If so, how?

 

Your help, as ever, gratefully received.

Link to comment
Share on other sites

simple answer, most likely not.

 

You could probably monitor "completions" by maybe using another language that is more actively involved with the client.

 

I was gonna suggest forcing a bandwidth cap, and at the end of echoing all the loops (in lets say 40 or 50 seconds) if the php script is still running, obviously it will reach the mysql insert and put it into the database that it was complete..

 

but, that causes certain issues,

 

for example:

max execution time problems (which could be fixed) possibly making your code less portable because some server configurations limit execution time aswell.. (I mean apache's max exec time, not php's php can be managed at runtime see:set_time_limit).

 

false positives.. If someone's internet connection is slower than 500kb/s, therefore your script will finish echoing the file before the user receives all the information, therefore if the user clicks cancel AFTER the file finishes outputting, but before he RECEIVES the whole file.. False positive :)

 

 

Link to comment
Share on other sites

simple answer, most likely not.

 

You could probably monitor "completions" by maybe using another language that is more actively involved with the client.

 

I was gonna suggest forcing a bandwidth cap, and at the end of echoing all the loops (in lets say 40 or 50 seconds) if the php script is still running, obviously it will reach the mysql insert and put it into the database that it was complete..

 

but, that causes certain issues,

 

for example:

max execution time problems (which could be fixed) possibly making your code less portable because some server configurations limit execution time aswell.. (I mean apache's max exec time, not php's php can be managed at runtime see:set_time_limit).

 

false positives.. If someone's internet connection is slower than 500kb/s, therefore your script will finish echoing the file before the user receives all the information, therefore if the user clicks cancel AFTER the file finishes outputting, but before he RECEIVES the whole file.. False positive :)

 

Thanks but I cannot risk the user being cut off.  He/she will have paid!  I saw here http://arstechnica.com/civis/viewtopic.php?f=20&t=355634 that searching the server logs might give a result.  I can capture the user identity at the start (IP address, browser type etc) if there was a way of PHP accessing the logs.  Still open to suggestions therefore, please...

Link to comment
Share on other sites

PHP can access any file that the user executing PHP has access to.

 

To get Apache to return the actual bytes sent by a request, you will probably have to modify your httpd.conf file. You have to change the LogFormat  to include either %O (more accurate, requires mod_logio) or %X

Full list: http://httpd.apache.org/docs/2.0/mod/mod_log_config.html

 

My LogFormat for access.log is

%h %l %u %t \"%r\" %>s %b %I %O %X

 

An incomplete request would look like this

127.0.0.1 - - [08/Nov/2011:15:24:33 -0800] "GET /file.exe HTTP/1.1" 200 476984768 377 208929103 X

 

While a completed request would look like this

127.0.0.1 - - [08/Nov/2011:15:25:12 -0800] "GET /file.exe HTTP/1.1" 200 476984768 377 476985103 +

 

An X means a cancelled request, while a +/- means the request completed. With %O, you can verify this. The number returned by %O will be slightly larger than that of the request size (%b), due to the headers being included in the size of %O.

 

It should be fairly easy to attach a user to this. If you track their IP/time of request/file requested, the only way a bad log file could be retrieved is if multiple people with the same IP downloaded the same file at the same second. The chances of this happening are quite slim, but it's something to keep in mind.

Link to comment
Share on other sites

Catch 22!  I am storing the files in question above the public access directory for security reasons so all I see in the logs is the PHP script that calls the download.  So either I relax my security or (advice please) could I persuade apache to log accesses to the directory in which the files are stored?

Link to comment
Share on other sites

  • 3 weeks later...

So I moved the downloads and protected the directory, so that was OK security wise.  And, after much mucking about with cPanel, I ended up editing httpd.conf directly and got Apache to generate the right logs.  However the log returns - one with a correct download and one a cancelled one - are identical:

 

[30/Nov/2011:12:08:04 +0000] "GET /test.php?do=download HTTP/1.1" 200 203753 "<my site>" "<Browser signature>" 204292 +

[30/Nov/2011:12:08:04 +0000] "GET /test.php?do=download HTTP/1.1" 200 203753 "<my site>" "<Browser signature>" 204292 +

 

So I am back to square one.  To restate the problem, I am trying to log when a user has completed a download, not when they started one and aborted it for whatever reason.  Your ideas would be most welcome.  I'm right royally stuck!

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.