Python – Flask: Static folder outside root directory

Question:

Just for fun, I am trying to understand how I can create a website with Python and Flask. That website has to run on my own computer and I will be the only client. So far I got most things I want to do working, but now I encounter a technical problem that I cannot solve.

On the client side I want to display images that are returned by the server. In my __init__.py I placed app = Flask(__name__, static_url_path='/static') and in my html document <img src="/static/images/2012035.jpg" height="150px">. This works like a charm.

But in fact, my images are in a directory d:genealogiedocumenten, which is outside the application directory and I do not want to copy more than 2000 files to the directory static/images.

I tried:

documenten = "d:genealogiedocumenten"
os.mkdir(documenten)

which gives a WinError 183 because the directory already exists.

I also tried:

documenten = "d:genealogiedocumenten"
app = Flask(__name__, static_url_path='documenten')

which gives a ValueError: urls must start with a leading slash.

I have seen quite a lot of similar questions here, but unfortunately I was unable to see how I could use the answers for my specific problem. Can I configure the website in such a way that I as a user can ask for say <img src="documenten/2012035.jpg" height="150px">, maybe with some or other localhost prefix? Any help is highly appreciated.

EDIT

What I want to do is to give the server access to directories that are outside the directory of the server. Maybe I can illustrate that by showing how easily this can be done in WAMP. There we only need to add a few lines to the file httpd.conf. For example:

Include "C:/wamp64/alias/*"

Alias /adressen "d:/adressen" 
<Directory "d:/adressen">
    Options Indexes FollowSymLinks Multiviews
    AllowOverride all
    Require all granted
</Directory>

Alias /genealogie "d:/genealogie" 
<Directory "d:/genealogie">
    Options Indexes FollowSymLinks Multiviews
    AllowOverride all
    Require all granted
</Directory>

The server and all its files are in c:/wamp64 and its subdirectories. But when we include <img src="http://localhost/genealogie/documenten/doc1064.jpg"> and <img src="http://localhost/adressen/doc5127.jpg"> in an html document, both images are nicely displayed, despite the fact that physically they reside far outside WAMP, even on different drives. So my question is: can we do this with FLASK as well?

Asked By: Fred Simons

||

Answers:

So you need to open the folder with your python code, extract the right picture and send it to your user?

You can do this with

file = "d:genealogiedocumentenyour_file_name" #you may consider a path library so you can do this in windows or Linux 
os.open(file) #you should really use a image library here. open is just a placeholder

In other words you want to open the image in your code (function, class, whatever) and then do to the image whatever you need to do. For example returning it to the user.

I personally would try to use something like this:

from flask import send_file 
file = "d:genealogiedocumentenyour_file_name" #you may consider a path library so you can do this in windows or Linux 
return send_file(file, mimetype='image/jpg') #in case of jpg image, you may opt to not use the mimetype

You can’t do this with

documenten = "d:genealogiedocumenten" 
app = Flask(__name__, static_url_path='documenten')

But why?
Basically the static_url_path is the url the user enters into the browser. This has nothing to do with your folder structure on the server. Heck, you do not even need to have folders on your server.

The structure of your internet presents does not have to related to the structure of your file system. Basically those are two completely different worlds that collide here.

The URL is used to structure the web hierarchically and mainly copes with organisational structures (domains, subdomains). The file server on the other hand can be structured in very many ways. Usually you want to represent the nature of the files and/or the age of the files.

By the way, the mkdir command creates folders, but you already have some.

Here is an answer to clarify how to use the send_file approach in an app setting with app.route.

import os
from flask import Flask, url_for, send_file

app = Flask(__name__)

# set the path where you store your assets - it can be outside of the root dir
app.config['CUSTOM_STATIC_PATH'] = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../archive'))

# have a route listening for requests
@app.route('/this/can/be/anything/<path:filename>')
def send_media(filename):
    path = os.path.join(app.config['CUSTOM_STATIC_PATH'], filename)
    return send_file(path)

# in your template, you can then use the following
# <img src="{{ url_for('send_media', filename='<dir>/<filename>') }}">
Answered By: scrollout
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.