Search code examples
pythonnginxflaskzipgunicorn

Inconsistent .zip download from Flask app over nginx/gunicorn


I have a Flask app deployed with Nginx and Gunicorn. The app has an endpoint that lets users download a specified zip file. Many of the zip files are small, but I have one large one - about 2.4GB - that is showing inconsistent download behavior. I have had no issues downloading the smaller files (which aren't larger than 500MB); the issues only seem to arise around the 2GB+ file size.

My initial code was:

@app.route('/zip')
def zip_download(name):

    file_name = '{}.zip'.format(name)
    
    zip_file = os.path.join(app.config['ZIP_PATH'], file_name)

    if os.path.exists(zip_file):
        return send_file(
                zip_file,
                as_attachment=True,
                attachment_filename=file_name)
    else:
         # tell user file doesn't exist

With this endpoint, I have not been able to download the entire 2.4GB file.

  • Using Chrome on Windows: the download would get to ~1GB and then restart the download completely. This cycle would seemingly repeat in a loop.
  • Using Chrome on MacOS: same behavior.

I proceeded to edit the code slightly to use the send_from_directory method instead:

@app.route('/zip')
def zip_download(name):

    file_name = '{}.zip'.format(name)
    
    zip_file = os.path.join(app.config['ZIP_PATH'], file_name)

    if os.path.exists(zip_file):
        return send_from_directory(app.config['ZIP_PATH'],
                                   file_name,
                                   as_attachment=True,
                                   mimetype='application/zip')

This time around the behavior is slightly different - better - but not completely right.

  • Chrome on Windows: Download completed after some time, but the zip was corrupted/damaged and I couldn't open the files (PDFs) inside.
  • Chrome on MacOS: No problems. Download worked and could open files.

So essentially, I'm trying to determine if these issues can be improved through Flask (e.g., config options relevant to downloads) or if I should explore options within nginx/gunicorn.


Solution

  • I ended up just using Nginx to serve the .zip files directly, and the download issues were resolved.

    None of the python solutions I attempted solved the issue, and most of what I read online indicated python/Flask was the sub-optimal solution for serving files.

    In my sites-available file for my app, I made a simple location {} to achieve this:

    location /download/url {
        alias /path/to/static/directory;
    }