File downloads in Django when file name contains non-ASCII chars.

Unfortunately there is no easy way to encode a file name within the Content-Disposition HTTP header when it contains non-ASCII chars. Meaning, if you are doing the following:

response['Content-Disposition'] = 'attachment; filename=Espanél.txt'

Then you will get an exception from Django when it tries to encode the headers as ASCII. The Content-Disposition header must be fully ASCII, and there is no standard way to encode i18n characters into this header. At least none that browser vendors all implement. The solution is actually quite simple, it involves removing the header altogether and putting the filename into the URL. The browser will cherry-pick the filename from the URL if the Content-Disposition header does not provide one, thus:

http://mysite.com/download/path/to/Espanél.txt

Will get you the result you want. You can configure the URL like so in urls.py:

    (r'^download(?P<path>.*)$', 'project.app.views.download'),

Which will invoke project.app.views.download function and pass it the full path as a parameter. Your view can then do the following.

def download(request, path):
    bytes = os.path.size(path)
    download = file(path, 'r')
    response = HttpResponse(download.read())
    response['Content-Disposition'] = 'attachment;'
    response['Content-Length'] = bytes
    return response

About this entry