Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: Create zipfile from S3 using django-storage

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.

like image 413
Gijsriet Avatar asked Sep 12 '25 14:09

Gijsriet


2 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.

like image 155
Gijsriet Avatar answered Sep 14 '25 04:09

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")
like image 39
dhruv kalaria Avatar answered Sep 14 '25 05:09

dhruv kalaria