views:

151

answers:

4

I have a personal project that's been online for sometime now. I've been keeping a tally of downloads by doing this:

  • When the user clicks the download link, it hits a PHP script that writes some information to a table.
  • Once the data is written, the script returns the path to the actual file.
  • The user then has the ability to save the file to their hard disk as if it was any other download.

This has worked well enough for sometime; however, it prevents users from being able to right-click > save target as... because they'll actually just see download.php appear in the "File Save.." dialog. Thus, the only way to download the project is to left-click on the link.

I'd like to improve the process so that a user can download the project using whatever method with which s/he is most comfortable. So, what are some better ways to transparently log downloads without getting in the user's way?

For what it's worth, the machine is a standard LAMP stack, so no .NET options here.

A: 

This is the reason a lot of sites use a download link that will take you to another page, which will start a download automatically when the page loads and also give the user a link to download directly. Mostly it's a way to get page views for ad impressions but it also helps track who is downloading their files more easily.

alxp
+1  A: 

This answer details how to use a transfer page to log the download as well as the start downloading the file as soon as someone clicks the link. I've recently tested it for right clicking.

I'm using a php middle-man to log file downloads. A URL formatted http://192.168.1.1/xfer.php?file=Li9zb25ncy9HTE9XX0xlYXZlIFlvdXIgSGF0IE9uLm1wMw results in the file name for both Save As... and left click in Firefox.

Here is my xfer.php

<?
$filename = base64_url_decode($_GET['file']);
if ($_GET['file']){
    header("Cache-Control: public");
    header("Content-Description: File Transfer");
    header('Content-disposition: attachment; filename='.str_replace(" ", "_",basename($filename)));
    header("Content-Transfer-Encoding: binary");
    header('Content-Length: '. filesize($filename));
    readfile($filename);
}
$fh = fopen("test.html","a");
fwrite($fh,basename($filename)."\n<br />");
fclose($fh);
function base64_url_decode($input) {
    return base64_decode(strtr($input, '-_,', '+/='));
}
?>

And the page that links to xfer.php is

$link = "xfer.php?file=".base64_url_encode("./songs/$key");

with $key being the file name and songs being the folder that the filenames are kept in.

Grant
+3  A: 

This is taken from the php-documentation, but is also possible using different script languages:

<?php
// We'll be outputting a PDF
header('Content-type: application/pdf');

// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');

// The PDF source is in original.pdf
readfile('original.pdf');
?>

The HTTP-Header Content-Disposition tells it to save it as a download.

Another option would be to inspect your log-files regularly, like every day using a script.

Georg
Yeah, I had considered the automated log-parsing route, but I like being able to have the information tabled in a database. Thanks for the PHP suggestion, though - I may end up going this route.
Tom
You could fill that database using the script, depending on how up-to-date the database has to be.
Georg
A: 

Set up Google Analytics? :)

nailitdown
I don't think Analytics tracks file downloads. Only pageviews.
Grant
On the file download link you can add an onClick that writes the event to analytics
nailitdown