Downloading multiple files in Flask

Question:

I am trying to provide the client side the option of downloading some files in Flask. There can be multiple files or a single file available for the user/client to download.

However I am not able to understand how to provide the user the option to download multiple files.

Here is what I have tried so far:


@app.route('/download_files')
def download():
    count=0
    download_list=[]
    for path in pathlib.Path("dir1/dir2").iterdir():
        if path.is_file():
            for i in names:
                if pathlib.PurePosixPath(path).stem == i:
                    count += 1
                    download_list.append(path)
    return send_file(download_list, as_attachment=True, mimetype="text/plain", download_name="Downloaded Files", attachment_filename="Generated Files")

This does not work properly even with a single file. The file type I am trying to download is text file with the extension .sql .

Will I somehow have to zip multiple files and then provide the download option? Please guide with my available options.

Asked By: eraisedtothepowerx

||

Answers:

You haven’t provided a code sample where you actually getting these files or this file. Minimum working example would be like this:

from flask import Flask, request

app = Flask(__name__)

@app.route('/download_files', methods=['POST'])
def download():
    file = request.files['file'] # for one file
    files = request.files.getlist("file[]") # if there're multiple files provided

if __name__ == "__main__":
    app.run()

After what your file variable will be an object of werkzeug.FileStorage and files variable will be a list of these objects.
And to download all these files you can check this question.

Answered By: adekability

In order to offer several files together as a download, you only have the option of compressing them in an archive.
In my example, all files that match the specified pattern are listed and compressed in a zip archive. This is written to the memory and sent by the server.

from flask import Flask
from flask import send_file
from glob import glob
from io import BytesIO
from zipfile import ZipFile
import os

app = Flask(__name__)

@app.route('/download')
def download():
    target = 'dir1/dir2'

    stream = BytesIO()
    with ZipFile(stream, 'w') as zf:
        for file in glob(os.path.join(target, '*.sql')):
            zf.write(file, os.path.basename(file))
    stream.seek(0)

    return send_file(
        stream,
        as_attachment=True,
        download_name='archive.zip'
    )
Answered By: Detlef
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.