+@cache.never_cache
+def download_shelf(request, slug):
+ """"
+ Create a ZIP archive on disk and transmit it in chunks of 8KB,
+ without loading the whole file into memory. A similar approach can
+ be used for large dynamic PDF files.
+ """
+ shelf = get_object_or_404(models.Tag, slug=slug, category='set')
+
+ # Create a ZIP archive
+ temp = temp = tempfile.TemporaryFile()
+ archive = zipfile.ZipFile(temp, 'w')
+
+ # Collect all books to include in ZIP archive
+ def collect_books(books):
+ result = []
+ for book in books:
+ if len(book.children.all()) == 0:
+ result.append(book)
+ else:
+ result += collect_books(book.children.all())
+ return result
+
+ for book in collect_books(models.Book.tagged.with_all(shelf)):
+ if book.pdf_file:
+ filename = book.pdf_file.path
+ archive.write(filename, str('%s.pdf' % book.slug))
+ if book.odt_file:
+ filename = book.odt_file.path
+ archive.write(filename, str('%s.odt' % book.slug))
+ if book.txt_file:
+ filename = book.txt_file.path
+ archive.write(filename, str('%s.txt' % book.slug))
+ archive.close()
+
+ response = HttpResponse(content_type='application/zip', mimetype='application/x-zip-compressed')
+ response['Content-Disposition'] = 'attachment; filename=%s.zip' % shelf.sort_key
+ response['Content-Length'] = temp.tell()
+
+ temp.seek(0)
+ response.write(temp.read())
+ return response
+
+