Skip to content

Commit e9cbf2f

Browse files
authored
Merge pull request #1 from DisruptiveLabs/partial-flush
Add partial flushing of ZipStreams
2 parents 7e861b1 + 4ea51e3 commit e9cbf2f

4 files changed

Lines changed: 55 additions & 4 deletions

File tree

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,27 @@ def zipball():
113113
response = Response(z, mimetype='application/zip')
114114
response.headers['Content-Disposition'] = 'attachment; filename={}'.format('files.zip')
115115
return response
116+
117+
# Partial flushing of the zip before closing
118+
119+
@app.route('/package.zip', methods=['GET'], endpoint='zipball')
120+
def zipball():
121+
def generate_zip_with_manifest():
122+
z = zipstream.ZipFile(mode='w', compression=ZIP_DEFLATED)
123+
124+
manifest = []
125+
for filename in os.listdir('/path/to/files'):
126+
z.write(os.path.join('/path/to/files', filename), arcname=filename)
127+
yield from z.flush()
128+
manifest.append(filename)
129+
130+
z.write_str('manifest.json', json.dumps(manifest).encode())
131+
132+
yield from z
133+
134+
response = Response(z, mimetype='application/zip')
135+
response.headers['Content-Disposition'] = 'attachment; filename={}'.format('files.zip')
136+
return response
116137
```
117138

118139
### django 1.5+

tests/test_zipstream.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,31 @@ def test_writestr(self):
9292

9393
os.remove(f.name)
9494

95+
def test_partial_writes(self):
96+
z = zipstream.ZipFile(mode='w')
97+
f = tempfile.NamedTemporaryFile(suffix='zip', delete=False)
98+
99+
with open(SAMPLE_FILE_RTF, 'rb') as fp:
100+
z.writestr('sample1.rtf', fp.read())
101+
102+
for chunk in z.flush():
103+
f.write(chunk)
104+
105+
with open(SAMPLE_FILE_RTF, 'rb') as fp:
106+
z.writestr('sample2.rtf', fp.read())
107+
108+
for chunk in z.flush():
109+
f.write(chunk)
110+
111+
for chunk in z:
112+
f.write(chunk)
113+
114+
f.close()
115+
z2 = zipfile.ZipFile(f.name, 'r')
116+
self.assertFalse(z2.testzip())
117+
118+
os.remove(f.name)
119+
95120
def test_write_iterable_no_archive(self):
96121
z = zipstream.ZipFile(mode='w')
97122
self.assertRaises(TypeError, z.write_iter, iterable=range(10))

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[tox]
2-
envlist = py26, py27, py32, py33, py34, py35, pypy
2+
envlist = py26, py27, py32, py33, py34, py35, py36, py37, pypy
33

44
[testenv]
55
deps=nose

zipstream/__init__.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,8 @@ def __init__(self, fileobj=None, mode='w', compression=ZIP_STORED, allowZip64=Fa
178178
self.paths_to_write = []
179179

180180
def __iter__(self):
181-
for kwargs in self.paths_to_write:
182-
for data in self.__write(**kwargs):
183-
yield data
181+
for data in self.flush():
182+
yield data
184183
for data in self.__close():
185184
yield data
186185

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

192+
def flush(self):
193+
while self.paths_to_write:
194+
kwargs = self.paths_to_write.pop()
195+
for data in self.__write(**kwargs):
196+
yield data
197+
193198
@property
194199
def comment(self):
195200
"""The comment text associated with the ZIP file."""

0 commit comments

Comments
 (0)