Django: Create zipfile from S3 using django-storage

Question:

I use django-storages and have user related content stored in folders on S3. Now I want users to have the ability to download all their files at once, preferably in a zip file. All the previous posts related to this are old or not working for me.

The closest to working code I have so far:

from io import BytesIO
import zipfile
from django.conf import settings
from ..models import Something
from django.core.files.storage import default_storage

class DownloadIncomeTaxFiles(View):

    def get(self, request, id):
        itr = Something.objects.get(id=id)
        files = itr.attachments
        zfname = 'somezip.zip'
        b =  BytesIO()
        with zipfile.ZipFile(b, 'w') as zf:
            for current_file in files:
                try:
                    fh = default_storage.open(current_file.file.name, "r")
                    zf.writestr(fh.name, bytes(fh.read()))
                except Exception as e:
                    print(e)
            response = HttpResponse(zf, content_type="application/x-zip-compressed")
            response['Content-Disposition'] = 'attachment; filename={}'.format(zfname)
            return response

This creates what looks like a zipfile but the only content it has is ‘<zipfile.ZipFile [closed]>’

I got many different results, mainly with errors like zipfile expecting string or bytes content while a FieldFile is provided. At this point I’m completely stuck.

Asked By: Gijsriet

||

Answers:

The problem was that I needed to revert back to the beginning of the file by adding

zf.seek(0)

just before returning the file in the HttpResponse.

Answered By: Gijsriet

There are 2 problems here. 1st is that even though you are creating a zipfile you are writing the data in bytesio object and 2nd you need to point the cursor at beginning as writer will point towards the end. So it should be:

b.seek(0)
response = HttpResponse(b, content_type="application/x-zip-compressed")
Answered By: dhruv kalaria