2

UPDATE: I got the zip file to be created, but the response still isn't working properly. Here's the updated code.

def index(request):
    if request.is_ajax():
        uploaded = request.body
        newstring = "{\"testdata\": [" + uploaded + "]}"
        data = json.loads(newstring)
        num_lines = sum(len(v) for v in data.itervalues())
        testing(data, num_lines)

        zip_subdir = 'testapi'
        zip_filename = '%s.zip' % zip_subdir

        zf = z.ZipFile(zip_filename, mode='w')
        zf.write('Test.xlsx')
        zf.close()

        zip_file = open(zip_filename, 'r')
        response = HttpResponse(zip_file, content_type='application/x-zip-compressed')
        response['Content-Disposition'] = 'attachment; filename=%s' % zip_filename
        return response

Just to make sure, I deleted the zip file and Excel spreadsheet, and after running the program, both were created properly. The Excel spreadsheet was populated with data, and a copy of it was put into the generated zip archive. However, it still is not getting sent to the user. Any idea what might be going wrong with the response? No errors are showing up, but the zip file isn't being delivered.

Original question below.


I'm trying to get my Django application to write files to a zip and send them to the user. This is part of the code I have in my view:

def index(request):
    if request.is_ajax():
        uploaded = request.body
        newstring = "{\"testdata\": [" + uploaded + "]}"
        data = json.loads(newstring)
        num_lines = sum(len(v) for v in data.itervalues())
        testing(data, num_lines)

        zip_subdir = 'testapi'
        zip_filename = '%s.zip' % zip_subdir

        s = StringIO.StringIO()
        zf = z.ZipFile(s, 'w')
        zf.write('Test.xlsx')
        zf.close()

        response = HttpResponse(s.getvalue(), content_type='application/x-zip-compressed')
        response['Content-Disposition'] = 'attachment; filename=%s' % zip_filename
        return response

Essentially, the user presses a button, an ajax request is made to get JSON from an external API, and then this JSON data is sent to the server and put into an Excel spreadsheet (called 'Test.xlsx'). All of that works properly.

The issue is that the zip archive ('testapi.zip') is not being created properly. What's odd is that it's the same code I used previously when the user uploaded a JSON dump via a form (rather than use an API), and it worked before. However, now it won't create a zip file. Additionally, even if I manually place a zip file called 'testapi.zip' in the proper directory, the response doesn't work (again, this used to work before - in the prior version of this app, the zip file was sent to the user and automatically downloaded). No errors are returned, but nothing happens.

Any idea what might be going on?

Jack
  • 140
  • 12

2 Answers2

1

The issue seems to be in the following code -

s = StringIO.StringIO()
zf = z.ZipFile(s, 'w')

You seem to be openning a zipfile in buffer , instead of creating a zipfile in the location with the name from zip_filename .

Try opening the file using the path/name of the file, instead of using StringIO.StringIO() . Like this -

zf = z.ZipFile(zip_filename,'w')

EDIT :

Try using absolute paths instead of relative path. Like -

zip_subdir = '/path/to/zip/file/testapi'
Niklas Rosencrantz
  • 25,640
  • 75
  • 229
  • 424
Anand S Kumar
  • 88,551
  • 18
  • 188
  • 176
  • I won't be able to give this a try until Monday at work - but thanks for the response! I'll give it a shot and let you know how it goes. – Jack Jun 20 '15 at 01:41
0

I'm not sure if this is really the best way to do it, but I figured out a way to get the file delivered. Based on this question, it looks like sending back a file as a response to an ajax request isn't possible.

Here's my new ajax call:

$("#btn1").click(function() {
    $.ajax({
        url: "https://api.github.com/",
        type: "GET",
        dataType: 'json',
        success: function(data) {
            $.ajax({
                url: "{% url 'index' %}",
                type: "POST",
                data: JSON.stringify(data),
                contentType: false,
                success: function(response, status, request) {
                    var disp = request.getResponseHeader('Content-Disposition');
                    if (disp && disp.search('attachment') != -1) {
                        var form = $('<form method="POST" action="' + "{% url 'index' %}" + '">' + "{% csrf_token %}");
                        $('body').append(form);
                        form.submit();
                    }
                },
                error: function(data) {
                    alert("There was an error posting the data to the server.");
                },
            });
        },
        error: function(data) {
            alert("There was an error retrieving the data from the API.");
        },
    });
});

And here's the two request handlers in views.py:

if request.is_ajax():
    uploaded = request.body
    newstring = "{\"testdata\": [" + uploaded + "]}"
    data = json.loads(newstring)
    num_lines = sum(len(v) for v in data.itervalues())
    testing(data, num_lines)

    zip_subdir = 'testapi'
    zip_filename = '%s.zip' % zip_subdir

    zf = z.ZipFile(zip_filename, mode='w')
    zf.write('Test.xlsx')
    zf.close()

if request.method == 'POST':
    zip_file = open('testapi.zip', 'rb')
    response = HttpResponse(zip_file, content_type='application/x-zip-compressed')
    response['Content-Disposition'] = 'attachment; filename=%s' % 'testapi.zip'
    return response

Essentially, the ajax GET request is used to get the JSON from the API, the ajax POST request (1) sends the JSON to the server to get placed into a spreadsheet and zipped up in a zip archive and (2) creates an invisible POST form which is used to deliver the zip file to the user.

Community
  • 1
  • 1
Jack
  • 140
  • 12