This question already has answers here:
How to serve static files in Flask
(24 answers)
Link to Flask static files with url_for
(2 answers)
Closed 4 years ago.
I have created a flask app that accesses images in a folder specified in a config file. For some reason, when I specify the full path to the folder (img_folder: '/user/userName/static/img/') I get a 404 error but when I specify the relative path (img_folder: './static/img/') it works. Looking at my terminal, the 404 error specifies the correct path and file, so the path is certainly correct.
What is going on? How can I use the full path without receiving a 404.
This is what it looks like when I specify the full path in the config folder:
img_folder : '/user/userName/static/img/'
This is the HTTP error when I specify the full path in the config:
127.0.0.1 - - [06/Jul/2018 11:26:25] "GET /user/userName/static/img/lion.jpg HTTP/1.1" 404
When I specify the relative path in the config folder like this:
img_folder : './static/img/'
I don't get the 404 error
In my flask app file, I have a route that uses the files from the folder as such:
files = os.listdir(img_folder)
#app.route('/', methods=['GET', 'POST'])
def init():
return render_template('display.html', file=files[0])
display.html
<!doctype html>
<div id='img_area'>
<img src="{{file}}"></img>
</div>
</html>
So the file is not being displayed when the full path is used, but is being displayed with the relative path.
Related
This question already has answers here:
Refering to a directory in a Flask app doesn't work unless the path is absolute
(1 answer)
Saving upload in Flask only saves to project root
(1 answer)
Get root path of Flask application
(2 answers)
Closed 4 years ago.
There are 2 functions or views located in the same file version.py, one for upload the other for downloading that file. The issue is that the send_file function keeps changing directories while opening the file.
Code 1:
File Upload function:
binfile = form.binfile.data
filename = secure_filename("arduino.bin")
#without the app folder
binfile.save(os.path.join(
app.config['UPLOAD_FOLDER'],
device_names.farm_id,
device_names.mqtt_id,
filename))
flash('File Uploaded', 'success')
File Download Function:
file_path = os.path.join(
app.config['UPLOAD_FOLDER'],
farm_id,
device_id,
'arduino.bin')
print(file_path)
response = make_response(send_file(
file_path,
mimetype='application/octet-stream',
as_attachment=True
))
response.headers['x-MD5'] = md5(file_path)
print(response.headers)
return response, 200
Here the file gets uploaded to the project root folder.
When I send a request for this file, I get this error:
[Errno 2] No such file or directory:
‘/home/maxwell/Desktop/python/aquaponics-monitor/app/firmware-manager/FARM0/node2/arduino.bin’
When I manually move the file to the 'app' folder I get no errors and a 200 response code while requesting. So I assume that the function is looking for the file inside the 'app' folder. I changed the upload location by adding 'app' to the path while uploading.
Code 2:
File Upload Function:
binfile = form.binfile.data
filename = secure_filename("arduino.bin")
#app folder included
binfile.save(os.path.join(
'app',
app.config['UPLOAD_FOLDER'],
device_names.farm_id,
device_names.mqtt_id,
filename))
flash('File Uploaded', 'success')
The file download function is the same as code 1. For this code I get this error:
[Errno 2] No such file or directory:
‘firmware-manager/FARM0/node2/arduino.bin’
The file download function now looks in the project root folder. I manually moved the file to the root folder this time and I again get a status code 200 and no errors when I send a request for it.
The only code change I made in the entire application is adding 'app' to the path in the File Upload function. Why is this happening?
I have a simple flask app with only an index.html page (so far), it's located in a folder with a bunch of javascript and CSS, which makes it a bit difficult to render.
I tried listing the file path for my HTML, however, it gives an internal server error, when I open the browser. Should I instead declare the path as a variable and pass that in?
I'm on Linux Ubuntu 16.04 btw.
here is my sample code:
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/")
#app.route("/home")
def home():
return render_template('/frontend/index.html')
here is how my directory is listed
--flaskwebsite
----routes.py
----routes.pyc
----templates
------frontend(other folders, javascript files etc)
------index.html
If Im seeing your folder structure correctly.
'templates/frontend/index.html'
Also you should have a separate template folder and a separate folder for static files such as css, js, pictures, and fonts.
This question already has answers here:
How to serve static files in Flask
(24 answers)
Closed 5 years ago.
I'm making an upload/download service just for fun but am struggling to serve files that are outside of static directory, which causes an issue because anyone could visit www.mysite.com/static and view the contents.
This is what I have so far. Forgive the ugly paths of my network storage :)
if not os.path.exists('\\ATTILA\\Development\\GIT\\MyCloud\\static\\'+ session['username']):
os.makedirs('\\\\ATTILA\\Development\\GIT\\MyCloud\\static\\'+ session['username'])
#Download links for all files
pathing = []
my_path = '\\\\ATTILA\\Development\\GIT\\MyCloud\\static\\'+ session['username'] + '\\'
os.chdir('\\\\ATTILA\\Development\\GIT\\MyCloud\\static\\'+ session['username'])
for myfile in glob.glob('*'):
downs = my_path + myfile
pathing.append(tuple([downs, myfile]))
In my template I have a simple for loop
{% for myfile, name in pathing %}
<a href='{{ myfile }}' download>{{ name }}</a><br>
{% endfor %}
So my view looks like this:
As it stands my files are downloadable, however if I change the file paths for the downloads to a folder outside of 'static' then instead of download links I get 404 errors that point to the URL + the file path like so www.mysite.com\ATTILLA\Development\some_other_folder any suggestions?
If you want place your app in production you need use solutions like a nginx for serving you static files.
Usually in development stage Flask work with regulary static files (css, js and another) self. It's normal.
If you want hide some private data or uploaded files you need use something like this:
from flask import Flask, make_response
...
#app.route('/file_downloads/<filename>')
def file_downloads(filename):
headers = {"Content-Disposition": "attachment; filename=%s" % filename}
with open('../tmp/you_private_file.zip', 'r') as f:
body = f.read()
return make_response((body, headers))
I followed the instructions from How to serve static files in Flask, but still couldn't get it working.
Here's my project structure:
Project_path
|
+--app
| |
| +--main.py
+--static
|
+--js
|
+--jquery-1.11.2.min.js
Here's main.py:
#app.route('/js/<path:path>')
def serve_static(path):
root_dir = os.path.dirname(os.getcwd())
print(os.path.join(root_dir, 'static', 'js', path))
return app.send_static_file(os.path.join(root_dir, 'static', 'js', path))
Here's index.html:
...
<script type="text/javascript" src="/js/jquery-1.11.2.min.js"></script>
...
And when I visit /, I could see the correct path of javascript file printed on the screen
which is Project_path/static/js/jquery-1.11.2.min.js.
But still, I got
127.0.0.1 - - [22/Dec/2014 11:26:30] "GET /js/jquery-1.11.2.min.js HTTP/1.1" 404 -
Any help is appreciated.
EDIT
After stepping through the send_static_file method, I find out what's going on. Basically, I shouldn't use abspath as argument, flask has a judgement in send_static_file:
if os.path.isabs(filename) or \
filename == '..' or \
filename.startswith('../'):
raise NotFound()
And since the filename I passed into is a abspath, flask raise NotFound().
It seems that what it supposed to be passed in is a relative path to self.static_folder(self is <Flask 'main'>), which, in my project, is Project_name/app/static. However, I didn't set static_folder myself which means flask thinks the static folder should be there.
I'm still trying to figure out what to do.
Finally got it working. use flask.send_from_directory
from flask import send_from_directory
#app.route('/js/<path:filename>')
def serve_static(filename):
root_dir = os.path.dirname(os.getcwd())
return send_from_directory(os.path.join(root_dir, 'static', 'js'), filename)
It is now clear to me that flask really hate people putting app.py or in my case main.py into a subdirectory. Use send_static_file only if your static folder is what flask thinks to be, i.e. a folder with name static in the same directory with app.py.
All you need to do is, pass the static_folder parameter to the initiator:
static_url_path – can be used to specify a different path for the
static files on the web. Defaults to the name of the static_folder
folder.
static_folder – the folder with static files that should be served at
static_url_path. Defaults to the 'static' folder in the root path of
the application.
app = Flask(__name__, static_folder=os.path.abspath('/foo/bar/zoo/'))
Now, flask will look for a directory named static in /foo/bar/zoo from where to serve static files. You only use send_from_directory if you are serving media files which may not be in the same location as static files.
You forgot to add 'static' in the last os.path.join in the return clause.
for me this one worked :
#app.route('/static/<path:filename>')
def serve_static(filename):
root_dir = os.path.dirname(os.getcwd())
return send_from_directory(os.path.join(root_dir, 'static', 'js'), filename)
beside adding this script into init
app._static_folder = os.path.abspath("static/")
app = Flask(__name__)
into __init__.py
One possible cause of 404 error for pages you just added (even if programmed correctly), is if you have previous versions of the script (.py file) still running: make sure to close out and end (terminate) the process.
I have a static directory that contains some resources (data files), and I can access the files directly: i.e., http://hello.com/static/dir/abc.pdf. However, I got error with the directory as the address: i.e., http://hello.com/static/dir.
Using flask, I can solve this issue by showing the contents of the directory.
#app.route('/static/<path:url>') #protect
def show(url):
content_dir = app.config['CONTENT_DIR']
directory = "%s/%s/box/%s" % (content_dir, url, url2)
result = []
if os.path.isdir(directory):
for file in os.listdir(directory):
content['url'] = '/static/...
result.append(content)
return render_template("box.html",...)
The issue is that with this route processing, the direct file accessing doesn't work any more as http://hello.com/static/dir/abc.pdf always triggers the show() method.
How can I redirect to the resource file (abc.pdf in the example), without being redirected to the show() method?
In your custom static route, check if the path is a file or a directory. If it's a file, serve it, otherwise show the directory index.
import os
from flask import send_file
path = os.path.join(app.config['CONTENT_DIR'], url, 'box', url2)
if os.path.isfile(path):
return send_file(path)
return render_template('box.html', ...)
Of course, since the path is specified by the url sent by the user, you should check that it's safe first.