Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,27 @@ def zipball():
response = Response(z, mimetype='application/zip')
response.headers['Content-Disposition'] = 'attachment; filename={}'.format('files.zip')
return response

# Partial flushing of the zip before closing

@app.route('/package.zip', methods=['GET'], endpoint='zipball')
def zipball():
def generate_zip_with_manifest():
z = zipstream.ZipFile(mode='w', compression=ZIP_DEFLATED)

manifest = []
for filename in os.listdir('/path/to/files'):
z.write(os.path.join('/path/to/files', filename), arcname=filename)
yield from z.flush()
manifest.append(filename)

z.write_str('manifest.json', json.dumps(manifest).encode())

yield from z

response = Response(z, mimetype='application/zip')
response.headers['Content-Disposition'] = 'attachment; filename={}'.format('files.zip')
return response
```

### django 1.5+
Expand Down
25 changes: 25 additions & 0 deletions tests/test_zipstream.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,31 @@ def test_writestr(self):

os.remove(f.name)

def test_partial_writes(self):
z = zipstream.ZipFile(mode='w')
f = tempfile.NamedTemporaryFile(suffix='zip', delete=False)

with open(SAMPLE_FILE_RTF, 'rb') as fp:
z.writestr('sample1.rtf', fp.read())

for chunk in z.flush():
f.write(chunk)

with open(SAMPLE_FILE_RTF, 'rb') as fp:
z.writestr('sample2.rtf', fp.read())

for chunk in z.flush():
f.write(chunk)

for chunk in z:
f.write(chunk)

f.close()
z2 = zipfile.ZipFile(f.name, 'r')
self.assertFalse(z2.testzip())

os.remove(f.name)

def test_write_iterable_no_archive(self):
z = zipstream.ZipFile(mode='w')
self.assertRaises(TypeError, z.write_iter, iterable=range(10))
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = py26, py27, py32, py33, py34, py35, pypy
envlist = py26, py27, py32, py33, py34, py35, py36, py37, pypy

[testenv]
deps=nose
Expand Down
11 changes: 8 additions & 3 deletions zipstream/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,8 @@ def __init__(self, fileobj=None, mode='w', compression=ZIP_STORED, allowZip64=Fa
self.paths_to_write = []

def __iter__(self):
for kwargs in self.paths_to_write:
for data in self.__write(**kwargs):
yield data
for data in self.flush():
yield data
for data in self.__close():
yield data

Expand All @@ -190,6 +189,12 @@ def __enter__(self):
def __exit__(self, type, value, traceback):
self.close()

def flush(self):
while self.paths_to_write:
kwargs = self.paths_to_write.pop()
for data in self.__write(**kwargs):
yield data

@property
def comment(self):
"""The comment text associated with the ZIP file."""
Expand Down