/    Sign up×
Community /Pin to ProfileBookmark

Can I use PHP to keep track of file downloads?

I’m no PHP guru… so far I’ve just done some PHP mail forms. All I want to do this time is write to a server side log, telling me whenever someone has “clicked” a link to download/view a PDF file. I don’t need to go the whole 9 yards of trying to track the origin of the person downloading, or whether its a robot or a human, or even whether the download completes. a simple timestamp will do. I short, I don’t expect any more accuracy then your typical visitor counter. Maybe PHP isn’t the easiest way to go here?

I guess it would be nice if I could simply sue the onclick() event in my <a href…> download link. But then that gets back to the (usually) ugly matter of trying to to get javascript and PHP to work together and share variables. I wonder if I’ll have to repeat that ugliness or if there will be a simpler way.

I’m aware that Google Analytics and some other companies offer a service to help with this problem. But I always learn more when the solution is code I can see and tweak, and doesn’t depend on a “free” service, that often becomes a “paid” service once they get you “hooked” πŸ˜‰

to post a comment
PHP

8 Comments(s) ↴

Copy linkTweet thisAlerts:
@ginerjmJan 29.2016 β€”Β If you used php to gather the filename and do the download instead of just using an anchor to point to the requested file, it would be easy. Write yourself a function that passes the filename as one of its arguments and then in your php handler for the submission of the request include a call to this function, passing the requested filename as that argument. Write one set of code and add one line (the function call) to each place/script that you have a request for a file to be downloaded.
Copy linkTweet thisAlerts:
@PeterPan_321authorJan 29.2016 β€”Β If you used php to gather the filename and do the download instead of just using an anchor to point to the requested file, it would be easy. Write yourself a function that passes the filename as one of its arguments and then in your php handler for the submission of the request include a call to this function, passing the requested filename as that argument. Write one set of code and add one line (the function call) to each place/script that you have a request for a file to be downloaded.[/QUOTE]

Hmmm... let me see if I understand. I suppose that much like my mail forms, I could have a PHP file that also includes the pretty HTML part, and use a form, maybe with a hidden input field containing the file name, and let the SUBMIT button POST the information back to a waiting PHP handler, that would then see the filename. So then, how would the PHP go about making the visitors browser start downloading and possibly displaying the file?
Copy linkTweet thisAlerts:
@NogDogJan 29.2016 β€”Β What ginerjm alludes to would be the most accurate: create a PHP file-server script that would accept an argument to specify the file to be downloaded, and then it actually fetches the file and sends with to the client (with applicable HTTP headers), and hopefully with enough security/validations to ensure it doesn't just send any file on the host. Less complete but possibly sufficient would be a bit of javascript attached to the link tags in question, probably via an onclick event, which would send a little ajax request to a PHP script to log what was requested, and then pass along the actual link reqest.
Copy linkTweet thisAlerts:
@NogDogJan 29.2016 β€”Β Here's a quick-and-dirty example to get you started (and not guaranteed to be bug-free!). The idea is that you would link to it with a URL query string parameter named "file", e.g.:
<i>
</i>http://example.com/get_file.php?file=foo_bar.pdf

And the get_file.php script would be something like:
[code=php]
<?php

$filePath = '/local/file/system/path/to/files/';

if(empty($_GET['file'])) {
notFound();
}

$fileName = $filePath . basename($_GET['file']);

if(!file_exists($fileName) or !is_readable($fileName)) {
notFound();
}

// for now assuming they're all PDF files:
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="'.basename($fileName).'"');
readfile($fileName);

function notFound()
{
header('HTTP/1.0 404 Not Found');
exit;
}
[/code]
Copy linkTweet thisAlerts:
@PeterPan_321authorJan 29.2016 β€”Β Thanks Terry! that's just what I needed... a starting point that illustrates the details of the mechanism so I can play and learn. So the http: query link would go in the original <a> tag, where I was formerly just putting a direct link to the file. So now instead the PHP file will be activated, and will be able to GET the filename as a passed variable, load it, and obviously from there I could easily log it (or even send myself an email if I was ambitious).

What is new to me here, and I suppose the mechanism is complicated, is the way the header() calls then work with the readfile() to send the file back through the client request. I'll try it, and hopefully with some reading about it I begin to understand. I suppose its the reverse of the process I've already used allow a user to send a file to me through one of my mail forms!

Anyway, thanks again!
Copy linkTweet thisAlerts:
@PeterPan_321authorJan 29.2016 β€”Β OK... This basically works. Two things though, (there's always 'things', right? ;-) ). First, if I pass a bad file or use a path that results in notFound() being triggered, the message in the header() call within the notFound() function doesn't appear. Probably I should use that header() call to re-direct to my actual 404.html file. Not sure, but its not a big deal.

The other disappointment though is that when I formerly directly linked the file in my <a> tag, most modern browsers that have a PDF plugin would not only download it, but would attempt to display it the browser window. With the PHP, it downloads it OK, but that's all it does. Could this also be related to a finer detail in the use of the header() calls?
Copy linkTweet thisAlerts:
@PeterPan_321authorJan 30.2016 β€”Β Think I got it now... thanks again. The notFound() redirect worked once I used header() to redirect to my actual 404 page. Also, by adding a variable to the passed data, I could let the user decide between download and view. The download basically uses the block of code as your example shows. To view, I simply use a header( 'Location: ' . $fullPathWithURL_t_file") type of construct. That will cause the browser to either view directly (as CHROME usually will) or download followed by launching a reader and opening the file (as Firefox will).

Of course the point was to log the downloads, which is now pretty easy from within the PHP.

Thanks again! learned something new and solved my problem. :-)
Γ—

Success!

Help @PeterPan_321 spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 β€” BETA 5.15,
whats_new: community page,
up_next: more Davinciβ€’003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinciβ€’003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,

tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,
)...