I'm trying to this to work: users can download their files from their
account page from a url like this:
http://example.com/account/download/a1234565789asedga-2/
for which django processes the authentication and then passes along
the info to nginx to serve the file.
However, I keep getting stuck. The view works in my local windows
machine (windows/apache), but not on my server (gentoo/nginx/fcgi).
*sigh* I'd really appreciate it if someone could take a look and help
me figure out what I'm doing wrong, please.
Here's the error message I'm getting from nginx:
2009/06/28 18:59:41 [error] 16316#0: *194 open() "/usr/
htmlBook.pdf.zip" failed (2: No such file or directory), client:
174.22.130.187, server:
example.com, request: "GET /account/download/
a1234565789asedga-2/ HTTP/1.1", upstream: "fastcgi://
127.0.0.1:1024",
host: "
example.com", referrer: "
http://example.com/account/shelf/"
I know what's wrong in the error message ('/usr/htmlBook.pdf.zip'),
but I can't tell *where* it's getting that incorrect location. As far
as I can tell, I'm sending it the actual location to grab the file and
file name ('/home/me/web/
example.com/public/media/books/
Book.pdf.zip'), but apparently I'm not getting that from django to
nginx correctly.
Here are the relevant bits of code:
# part of the views.py
def download_file(request, dlkey=None, ftype=None):
if request.user.is_authenticated():
try:
k = Ebook.objects.select_related().filter
(ftype__exact=ftype).filter
(book__orderdetail__dlkey__exact=dlkey).filter
(book__orderdetail__medium__exact='E')[:1]
for e in k:
ebook = e.ebook
filename = os.path.join(PROTECTED_DIR, os.path.basename
(ebook))
response = HttpResponse()
response['X-Accel-Redirect'] = ebook
response['Content-Disposition'] =
"attachment;filename=" + ebook
return response
except Exception:
raise Http404
# part of the nginx configuration for the domain:
location ^~ /account/download/ {
include /etc/nginx/
fastcgi_params_django;
fastcgi_pass
127.0.0.1:1024;
alias /home/me/web/
example.com/
public/media/books/;
}
location ^~ /media/books/ {
root /home/me/web/
example.com/
public;
internal;
}
# in settings.py
PROTECTED_DIR = '/home/me/web/
example.com/public/media/books/'
If I do this in the view:
response['X-Accel-Redirect'] = ebook
I get the error message from above with nginx trying to grab the file
from the wrong location, but the browser presents me with a correctly
named (broken) zip file for download. (WinRAR says "The archive is
either in unknown format or damaged.")
If I do what I actually think I should be doing in the view:
response['X-Accel-Redirect'] = filename
I get a django 404 page with this as the request URL after clicking on
the download link:
http://example.com/home/me/web/example.com/public/media/books/Book.pdf.zip/
The frustrating thing is this works (I can save the requested zip file
and open it just fine) on my windows setup with this part changed in
the views.py:
for e in k:
ebook = e.ebook
filename = os.path.join(PROTECTED_DIR, os.path.basename
(ebook))
handle = open(filename, 'rb')
book = handle.read()
handle.close()
response = HttpResponse(book)
response['Content-Type'] = 'application/x-zip-
compressed'
response['Content-Disposition'] =
"attachment;filename=" + ebook
return response
When I add the open() bit in the live version and change to:
response['X-Accel-Redirect'] = book
it gives me a big old mess. (Presumably because I'm trying to give it
the file itself, rather than the URI that X-Accel-Redirect requires
[1].)
So, the conclusion I've come to after many hours of reading docs,
trial and error, googling, and researching errors is that I haven't a
clue where it is that I'm telling django to send the wrong URL to
nginx. Help!
Thanks -
Annie
[1]
http://wiki.nginx.org/NginxXSendfile