1

My goal is to parse a series of strings into a series of text files that are compressed as a Zip file and downloaded by a web app using Django's HTTP Response.

Developing locally in PyCharm, my method outputs a Zip file called "123.zip" which contains 6 individual files named "123_1", "123_2 etc". containing the letters from my phrase with no problem.

The issue is when I push the code to my web app and include the Django HTTP Response the file will download but when I go to extract it it produces "123.zip.cpzg". Extracting that in turn gives me 123.zip(1) in a frustrating infinite loop. Any suggestions where I'm going wrong?

Code that works locally to produce "123.zip":

def create_text_files1():
    JobNumber = "123"
    z = zipfile.ZipFile(JobNumber +".zip", mode ="w")
    phrase = "A, B, C, D, EF, G"
    words = phrase.split(",")
    x =0

    for word in words:
        word.encode(encoding="UTF-8")
        x = x + 1
        z.writestr(JobNumber +"_" + str(x) + ".txt", word)
    z.close()

Additional part of the method in my web app:

    response = HTTPResponse(z, content_type ='application/zip')
    response['Content-Disposition'] = "attachment; filename='" + str(jobNumber) + "_AHTextFiles.zip'"
HGC
  • 13
  • 3

1 Answers1

0

Take a closer look at the example provided in this answer.

Notice a StringIO is opened, the zipFile is called with the StringIO as a "File-Like Object", and then, crucially, after the zipFile is closed, the StringIO is returned in the HTTPResponse.

# Open StringIO to grab in-memory ZIP contents
s = StringIO.StringIO()

# The zip compressor
zf = zipfile.ZipFile(s, "w")

# Grab ZIP file from in-memory, make response with correct MIME-type
resp = HttpResponse(s.getvalue(), mimetype = "application/x-zip-co mpressed")

I would recommend a few things in your case.

  1. Use BytesIO for forward compatibility
  2. Take advantage of ZipFile's built in context manager
  3. In your Content-Disposition, be careful of "jobNumber" vs "JobNumber"

Try something like this:

def print_nozzle_txt(request):
    JobNumber = "123"
    phrase = "A, B, C, D, EF, G"
    words = phrase.split(",")
    x =0

    byteStream = io.BytesIO()

    with zipfile.ZipFile(byteStream, mode='w', compression=zipfile.ZIP_DEFLATED,) as zf:
        for word in words:
            word.encode(encoding="UTF-8")
            x = x + 1
            zf.writestr(JobNumber + "_" + str(x) + ".txt", word)

    response = HttpResponse(byteStream.getvalue(), content_type='application/x-zip-compressed')
    response['Content-Disposition'] = "attachment; filename='" + str(JobNumber) + "_AHTextFiles.zip'"
    return response