I am a little new to Django so please bear with me.
I'm using zipstream from here and have a Django view that returns a zip file of all file attachments which are all hosted on Amazon S3. But the zip files are all coming up as corrupt when I download them, that is, I can't open them. I have tried verifying the files with unzip -t
but the errors are not very helpful.
file_paths = [fa.file.url for fa in file_attachments.all()]
zf = zipstream.ZipFile(mode='w', compression=zipstream.ZIP_DEFLATED)
zip_subdir = "Attachments-%s" % (request_id)
for file_path in file_paths:
file_dir, file_name = os.path.split(file_path)
zf.writestr(file_name, urllib.urlopen(file_path).read())
zip_filename = "%s.zip" % (zip_subdir)
response = StreamingHttpResponse(zf, mimetype='application/zip')
response['Content-Disposition'] = \
'attachment; filename={}'.format(zip_filename)
return response
Any ideas?
Solved it.
s = StringIO.StringIO()
with zipstream.ZipFile(s, mode='w', compression=zipstream.ZIP_DEFLATED) as zf:
#could fail on url open.
for file_path in file_paths:
file_dir, file_name = os.path.split(file_path)
try:
file_contents = urllib.urlopen(file_path).read()
zf.writestr(file_name, file_contents)
except IOError: #connection cannot be made
logging.error()
response = StreamingHttpResponse(s.getvalue(), mimetype='application/octet-stream')
response['Content-Disposition'] = \
'attachment; filename={}'.format("%s" % (request_id))
return response
You should close the ZipFile
when you're done writing to it. Otherwise, to quote the documentation, "essential records will not be written" until you do.
The cleanest way to do it is using the with
statement:
with zipstream.ZipFile(mode='w', compression=zipstream.ZIP_DEFLATED) as zf:
# ...write to zf...