J. Scull
J. Scull

Reputation: 319

Streaming & downloading Large CSV files using StreamingHttpResponse

So the issue I am facing is trying to get our webservers export to CSV button working, one requirement is the file cannot be saved locally and must be streamed straight to the client. At the moment I am just trying to get a basic CSV file streamed and saved on the local machine from the server before I worry about rendering actual data.

So, I have, on button click a post to my views where I wish to render then return a response. This was a $.ajax function but I have since changed it during testing and it now looks like this looks like:

$("#exportbutton").click(function(e){
    $.post("{% url 'doner:download' %}", function(data)
    {
        console.log(data);
    });
  })

The code in the view looks like this (which happens to be a CTRL+V of an example from SO):

def download(request):
    def stream():
        buffer_ = io.StringIO()
        writer = csv.writer(buffer_)
        for row in rows:
            writer.writerow(row)
            buffer_.seek(0)
            data = buffer_.read()
            buffer_.seek(0)
            buffer_.truncate()
            yield data

    response = StreamingHttpResponse(
        stream(), content_type='text/csv'
    )
    disposition = "attachment; filename=file.csv"
    response['Content-Disposition'] = disposition

    return response

So after a lot of tinkering this is as far as I have got, it will 'stream'(?) the data back into the HTML page, the console.log will output the 'files' data however I do not get any form of a file or a download, just the log in the console of the data.

I don't know if I have missunderstood how StreamingHttpResponse works and I'm meant to do something more on the client side in order to download it past the stream but I've read the docs and I'm no more clear.

Any help would be greatly appreciated as I'm stumped, cheers guys!

Upvotes: 1

Views: 1789

Answers (1)

J. Scull
J. Scull

Reputation: 319

The issue I was facing was posting using jQuery, apparently the browser is not able to download a file using AJAX, so in order to fix this part and get the file download, all I did was inside the AJAX (making sure it get generated alright before it's downloaded) add the line location.replace('doner/download'); and that was it...

Now the jQuery looks like this:

$("#exportbutton").click(function(e){
    $.post("{% url 'doner:download' %}", function(data)
    {
        console.log(data);
        location.replace("{% url 'doner:download' %}");
    });
  })

And everything works as needed!

Upvotes: 1

Related Questions