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
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 filesystemstatic_url_path
sets the path used within the URLIf neither of the variables are set, it defaults to 'static'
for both.
Hopefully this is what you're asking.