6

Using Django, I want to make some data available for download.

My jQuery call looks like this so far:

$.getJSON("/get_data", 
            { users: users, study: "{{study.id}}" } ,
            function(json){
                alert('some data!');
            }
);

This calls one of my Django views, which in turn generates some JSON and attempts to make that JSON text in a file to download

jsonResponse = json.dumps(data, cls=DjangoJSONEncoder)

jsonFile = cStringIO.StringIO()
jsonFile.write(jsonResponse)

response = HttpResponse(jsonFile, mimetype='application/json')
response['Content-Disposition'] = 'attachment; filename=data.txt'

return response

However, this does not work. After looking around for a while, I believe I should change something on both ends – the Javascript and the python/Django code – but I'm unclear what exactly.

For Python, my main concern is in the use of cStringIO (especially the fact that I cannot execute close on jsonFile before returning without prompting a "ValueError: I/O operation on closed file").

Maybe I should also be using a FileWrapper (like in this post), but I get identical results with and without it.

For Javascript, I'm not sure what should go into my success handler function.

Any pointers would be greatly appreciated!

Community
  • 1
  • 1
arturomp
  • 28,790
  • 10
  • 43
  • 72
  • You want to have user see a file download dialog (save, run cancel) or simply want to send JSON data for javascript use? – xbtsw May 21 '12 at 22:25
  • The former - I'd like to make a "save" browser dialog come up (which, from my understanding, should happen with the "Content-Disposition" header, correct?) – arturomp May 21 '12 at 22:47
  • @amp, that forces a _download_ as opposed to an in-browser rendering. Forcing a save file doesn't appear to be something we can do... for example I have all of my downloads going straight to my downloads directory. Google searches reveal similar statements... – Yuji 'Tomita' Tomita May 22 '12 at 00:04

1 Answers1

8

The classic solution for this is to use an hidden iframe.

In your urls.py

url(r'^test/getFile', 'getFile')

In your views.py

def getFile(request):
    fileContent = "Your name is %s" % request.GET['name']
    res = HttpResponse(fileContent)
    res['Content-Disposition'] = 'attachment; filename=yourname.txt'
    return res

On your page

<script type="text/javascript">
    var data = {name: 'Jon'};
    $(function(){
        $("body").append('<iframe src="/test/getFile?'+ $.param(data) + '" style="display: none;" ></iframe>');
    });
</script>
xbtsw
  • 684
  • 5
  • 12