views:

46

answers:

3

I have a site which enables the user to download certain files. However I want to keep a download count for each file so going the usual way by putting the static files on a different subdomain and then letting apache do the heavy lifting is not a way as well as HttpResponseRedirecting the user to a subdomain isn't good because then the user 'sees' the proper download url and can therefore download the file without incrementing the download count. I could just build a view which then serve()s the file however i am worried about that "big fat disclaimer". How would you/did you implement this? I am quite shure I am not the only one with that problem.

About the Platform: I am using apache and mod_wsgi.

Thank you

A: 

I did this with django-counter not to long ago. Lets you keep track of the counts in the admin. http://github.com/svetlyak40wt/django-counter/

timg
i was hoping for a more general answer since keeping a download count will not be the only logic going on :)
niklasfi
+2  A: 

We've implemented a system where we needed to control download access to (largish) static files, naturally not wanting Django to serve them itself. We came up with a scheme whereby the Django app, after validating that the user was allowed to download the file (or increment a counter, in your case) we would create a randomly-named symlink to the file, which Apache had access to (be careful: make sure directory indexing is off etc), and then redirect the user to that symlink to be served by Apache.

We have a "cleanup" cronjob that cleans up symlink a minute after they're created, so if they want to download it again, they have to go through Django and have it counted again. Now, theoretically they could download it more than once in that time, but is that likely to happen? You could clean up more than every minute: Apache just needs the symlink to exist at the beginning of the download, not throughout the whole thing.

I'd be curious to know how others address this problem, as I agree with the OP that it is a common scenario.

psj
this sounds like a good idea, but I would like to keep decent url-design and enable the user to download a file twice from the same location
niklasfi
Sure, but this model still supports that. The canonical URL for the file is the Django-controlled URL, which is consistent and decent etc, and the only URL the user sees. The redirect to the Apache-served symlink is more a "plumbing detail" that the user doesn't notice -- the browser follows the redirect transparently.
psj
A: 

psj's answer is definitely one viable option. Another option you should investigate is putting a reverse-proxy server in-front of apache like Perlbal which supports "X-REPROXY-URL" headers.

Once you have the reverse-proxy server in place, instead of sending the user a redirect response, you can send a response with the "X-REPROXY-URL" header set to a URL where the proxy server can access but the user can't. The proxy server will then read in the file from the location you sent in the header, and then serve it out to your client. They'll do so in an efficient way and since all your Django app server needs to send is a response with a header set, it is free to handle another request.

SeanOC