Search code examples
flaskstatic-files

How to properly server static files from a Flask server?


What is the proper way of serving static files (images, PDFs, Docs etc) from a flask server?

I have used the send_from_directory method before and it works fine. Here is my implementation:

@app.route('/public/assignments/<path:filename>')
def file(filename):
    return send_from_directory("./public/assignments/", filename, as_attachment=True)

However if I have multiple different folders, it can get a bit hectic and repetitive because you are essentially writing the same code but for different file locations - meaning if I wanted to display files for a user instead of an assignment, I'd have to change it to /public/users/<path:filename> instead of /public/assignments/<path:filename>.

The way I thought of solving this is essentially making a /file/<path:filepath> route, where the filepath is the entire path to the destination folder + the file name and extension, instead of just the file name and extension. Then I did some formatting and separated the parent directory from the file itself and used that data when calling the send_from_directory function:

@app.route('/file/<path:filepath>', methods=["GET"])
def general_static_files(filepath):
    filepath = filepath.split("/")
    _dir = ""
    for i, p in enumerate(filepath):
        if i < len(filepath) - 1:
            _dir = _dir + (p + "/")
    return send_from_directory(("./" + _dir), filepath[len(filepath) - 1], as_attachment=True)

if we simulate the following request to this route:

curl http://127.0.0.1:5000/file/public/files/jobs/images/job_43_image_1.jpg

the _dir variable will hold the ./public/files/jobs/images/ value, and then filepath[len(filepath) - 1] holds the job_43_image_1.jpg value.

If i hit this route, I get a 404 - Not Found response, but all the code in the route body is being executed.

I suspect that the send_from_directory function is the reason why I'm getting a 404 - Not Found. However, I do have the image job_43_image_1.jpg stored inside the /public/files/jobs/images/ directory.

I'm afraid I don't see a lot I can do here except hope that someone has encountered the same issue/problem and found a way to fix it.

Here is the folder tree:

├── [2050]  app.py
├── [2050]  public
│   ├── [2050]  etc
│   └── [2050]  files
│       ├── [2050]  jobs
│       │   ├── [2050]  files
│       │   └── [2050]  images
│       │       ├── [2050]  job_41_image_decline_1.jpg
│       │       ├── [2050]  job_41_image_decline_2554.jpg
│       │       ├── [2050]  ...
│       ├── [2050]  shop
│       └── [2050]  videos
└── [2050]  server_crash.log

Edit 1: I have set up the static_url_path. I have no reason to believe that that could be the cause of my problem.

Edit 2: Added tree


Solution

  • Pass these arguments when you initialise the app:

    app = Flask(__name__, static_folder='public',
                          static_url_path='frontend_public' )
    

    This would make the file public/blah.txt available at http://example.com/frontend_public/blah.txt.

    • static_folder sets the folder on the filesystem
    • static_url_path sets the path used within the URL

    If neither of the variables are set, it defaults to 'static' for both.

    Hopefully this is what you're asking.