2

I have a folder structure on my web server that I would like to serve as a zipped archive through Flask.

Serving a file through Flask is pretty straight forward through Flasks send_file:

return send_file(my_file,
                     attachment_filename=fileName,
                     as_attachment=True)

Zipping can get accomplished in various ways like with shutil.make_archive or zipfile, but i cannot figure out how to zip the whole directory in memory and then send it without saving anything to disk. shutil.make_archive seem to only be able to create archives on disk. The examples on zipfile found on the Internet are mainly about serving single files.

How would I tie this together in a single method without having to save everything to disk? Preferably using BytesIO.

Fontanka16
  • 1,161
  • 1
  • 9
  • 37
  • Any feedback on how to improve this question would be appreciated. I had a really hard time figuring this out, and with three upvotes, it seems like a needed question. – Fontanka16 Feb 03 '21 at 13:37

1 Answers1

9
import time
from io import BytesIO
import zipfile
import os
from flask import send_file


@app.route('/zipped_data')
def zipped_data():
    timestr = time.strftime("%Y%m%d-%H%M%S")
    fileName = "my_data_dump_{}.zip".format(timestr)
    memory_file = BytesIO()
    file_path = '/home/data/'
    with zipfile.ZipFile(memory_file, 'w', zipfile.ZIP_DEFLATED) as zipf:
          for root, dirs, files in os.walk(file_path):
                    for file in files:
                              zipf.write(os.path.join(root, file))
    memory_file.seek(0)
    return send_file(memory_file,
                     attachment_filename=fileName,
                     as_attachment=True)
Fontanka16
  • 1,161
  • 1
  • 9
  • 37
  • 1
    Answering own questions is not discouraged. See https://stackoverflow.blog/2011/07/01/its-ok-to-ask-and-answer-your-own-questions/ – Matthias Dec 21 '18 at 08:04
  • 1
    Very helpful! In my case I was passing back zipped bytes from a block of code running on a remote machine and so my return was different. Used equivalent of `return memory_file.getvalue()` from the function running remotely and then wrote that returned item at local namespace using `wb` with `with open` and saving with `.zip` extension. In case maybe it will help others new to making the zipped files with Python, I found [here](https://stackoverflow.com/a/54202259/8508004) helped in understanding the `memory_file.seek(0)` line. – Wayne Aug 15 '22 at 19:43