My images of plots won't display. I store them separately in "uploads" directory (not static nor its sub).
#app.route('/job/<job_id>')
def get_job(job_id):
directory_name = db.get(job_id)
if directory_name is False:
abort(404)
return render_template('job.html', directory_name=directory_name)
Im passing directory_name to the html:
<html>
<body>
<img src="{{url_for('send_image', directory_name=directory_name)}}" >
</body>
</html>
Which refers to other view that should browse my directories.
#app.route('/uploads/<directory_name>/plot.png')
def send_image(directory_name, job_id):
return send_from_directory("uploads", directory_name + "plot.png")
However i still get nothing. What I am doing wrong? Is "static" the only directory that flask can handle?
Related
I followed this tutorial and everything works except for downloading the images that were uploaded. I get 404 errors for everything I try to display in the browser. I can see the images on the hard drive just fine, but they do not download on the /uploads route. ANy ideas?
#bp.route('/uploads/<filename>')
def upload(filename):
print('path: '+str(current_app.config['PRODUCT_UPLOAD_PATH'])+', filename: '+filename)
return send_from_directory(current_app.config['PRODUCT_UPLOAD_PATH'], filename)
Here is the html template that loads the files. The filenames popup proeprly, but the route just shows 404 errors for all the images.
{% for file in files %}
<img src="{{ url_for('main.upload', filename=file) }}" style="width: 64px">
{% endfor %}
config.py to show where the directories are pointing.
MAX_CONTENT_LENGTH = 1024 * 1024
UPLOAD_EXTENSIONS = ['.jpg', '.png', '.gif']
PRODUCT_UPLOAD_PATH = 'uploads/products/'
Here is the solution I found that makes this work. Thanks for the help from everyone!
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config(object):
#This string does not work
#PRODUCT_UPLOAD_PATH = 'uploads/products/'
#This is the proper way to configure file paths
PRODUCT_UPLOAD_PATH = os.path.join(basedir, 'uploads', 'products')
is there a posibility to create an easy function like
def createPath(name):
path = "abcd.jpg"
finalPath = name + "/" + path
return finalPath
(...)
path = createPath("folder1")
return render_template('index.html', PATH=path)
and use the returned finalPath in a html file like
<img src=" {{PATH}} " alt="Trulli" width="500" height="333">
It does not work.
I don't know how to use variables in html.
Thank you a lot
By any chance, are you sure your url name + "/" + path is served by a web server ? If you want to serve static file you can have a look at https://flask.palletsprojects.com/en/1.1.x/tutorial/static/
This works for me :
from flask import Flask,render_template_string
app = Flask(__name__)
#app.route("/", methods=["GET"])
def hello_world():
name = "flask-logo.png"
path = createPath(name)
return render_template_string("""<!DOCTYPE html>
<html>
<head><title>Test</title></head>
<body>
<h1>Hello World</h1>
<img src="{{PATH}}" alt="Trulli" width="500" height="333">
</body>
</html>
""",PATH=path)
def createPath(name):
path = "https://flask.palletsprojects.com/en/1.1.x/_images"
finalPath = path + "/" + name
return finalPath
if __name__ == '__main__':
app.run()
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))
So, I've been trying to add an image uploader to my code, but I've been running into issues. Even though I thought I had my upload_folder configured properly, I keep getting errors like: IOError: [Errno 2] No such file or directory: '/static/uploads/compressor.jpg' even though the file/directory exists.
Here's the code:
in config.py
UPLOAD_FOLDER = 'static/uploads'
in init.py
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
in views.py
#app.route('/fileupload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
#check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
#submit an empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('uploaded_file',
filename=filename))
return '''
<!doctype html>
<title>Upload new File</title>
<h>UPload new file</h1>
<form action="" method=post enctype=multipart/form-data>
<p><input type=file name=file>
<input type=submit value=Upload>
</form>
'''
#app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename)
My folder structure is as follows
/project folder
--/app
----/static
--------/uploads
----/templates
----_init__.py
----views.py
--config.py
When I use /tmp/ to store it in memory the uploader works no problem. I assume it's not looking in the proper path for my folder. Can anyone help here? I'm a very amateur python developer.
Both /tmp and /static/uploads/.., are absolute paths. And your code is looking in the / folder instead of looking in your project's folder. You should use the absolute path to point at your folder /path/to/your/project/static/uploads/.. or use a path relative to the code being executed such as ./static/uploads.
You can also use the following snippet to generate the absolute path:
from os.path import join, dirname, realpath
UPLOADS_PATH = join(dirname(realpath(__file__)), 'static/uploads/..')
This worked for me:
basedir = os.path.abspath(os.path.dirname(__file__))
file.save(os.path.join(basedir, app.config['UPLOAD_FOLDER'], filename))
#jidesakin's solutions works but here is another solution:
Move your uploads folder from static directory back to your project directory where your app folder is, the folder where your app and environment folders are.
Your structure will be like:
'projectfolder
--/app
--config.py
--__init__.py
------/static
------/templates
------config
--uploads
Then change the content of you upload folder from 'static/uploads' to 'uploads' ...
Is it possible to use flask to browse through a directory with files?
My code never seems to work correctly as weird appending between strings happens.
Also I don`t know how to implement a kind of check whether the path is a file or a folder.
Here is my Flask app.route:
#app.route('/files', defaults={'folder': None,'sub_folder': None}, methods=['GET'])
#app.route('/files/<folder>', defaults={'sub_folder': None}, methods=['GET'])
#app.route('/files/<folder>/<sub_folder>', methods=['GET'])
def files(folder,sub_folder):
basedir = 'files/'
directory = ''
if folder != None:
directory = directory + '/' + folder
if sub_folder != None:
directory = directory + '/' + sub_folder
files = os.listdir(basedir + directory)
return render_template('files.html',files=files,directory=basedir + directory,currdir=directory)
and here is my html template, if anyone could give me some pointers it would be greatly appreciated!
<body>
<h2>Files {{ currdir }}</h2> </br>
{% for name in files: %}
{{ name }} </br></br>
{% endfor %}
</body>s.html',files=files,directory=basedir + directory,currdir=directory)
A path converter (docs link) in the url structure is better than hardcoding all the different possible path structures.
os.path.exists can be used to check if the path is valid and os.path.isfile and os.path.isdir for checking if the path is a file or a directory, respectively.
Endpoint:
#app.route('/', defaults={'req_path': ''})
#app.route('/<path:req_path>')
def dir_listing(req_path):
BASE_DIR = '/Users/vivek/Desktop'
# Joining the base and the requested path
abs_path = os.path.join(BASE_DIR, req_path)
# Return 404 if path doesn't exist
if not os.path.exists(abs_path):
return abort(404)
# Check if path is a file and serve
if os.path.isfile(abs_path):
return send_file(abs_path)
# Show directory contents
files = os.listdir(abs_path)
return render_template('files.html', files=files)
Template (Now with directory browsing :) ):
<ul>
{% for file in files %}
<li>
<a href="{{ (request.path + '/' if request.path != '/' else '') + file }}">
{{ (request.path + '/' if request.path != '/' else '') + file }}
</a>
</li>
{% endfor %}
</ul>
Note: abort and send_file functions were imported from flask.
Here is a working example.
# app.py
from flask import Flask
from flask_autoindex import AutoIndex
app = Flask(__name__)
ppath = "/" # update your own parent directory here
app = Flask(__name__)
AutoIndex(app, browse_root=ppath)
if __name__ == "__main__":
app.run()
Here is a working repo
https://github.com/MrAmbiG/folderview
I created this function for my project ... it is working perfectly ... it start browsing at this folder /home/myuser/myfolder
#app.route('/myfolder/<path:folders>')
#app.route('/myfolder/')
def mybrowser(folders=''):
environ = flask.request.environ
path = environ.get('PATH_INFO')
path = path.lower()
#if path=='/myfolder': return flask.redirect(path+'/',code=307)
os_path = '/home/myuser'+path.rstrip('/')
if path.endswith('/'):
HTML_HEADER = """<html><head><title>Index of {path_title}</title></head><body bgcolor="white"><h1>Index of {path_title}</h1><hr><pre>../\n"""
HTML_FOOTER = "</pre><hr></body></html>"
path_title = os_path.split('myuser')[1]+'/'
html = HTML_HEADER.format(path_title=path_title)
import os,time
files = os.listdir(os_path)
for file in files:
path = os_path+'/'+file
size = str(os.path.getsize(path))
date = os.path.getmtime(path)
date = time.gmtime(date)
date = time.strftime('%d-%b-%Y %H:%M',date)
spaces1 = ' '*(50-len(file))
spaces2 = ' '*(20-len(size))
if os.path.isdir(path): html += '' + file + '/'+spaces1+date+spaces2+' -\n'
else: html += '' + file + ''+spaces1+' '+date+spaces2+size+'\n'
html += HTML_FOOTER
#open(os_path+'/index.html','w').write(html)
response_headers = {'Content-Type':'text/html','Content-Length':str(len(html))}
status = '200 OK'
response = flask.Response(html,status=status,headers=response_headers)
else:
response = flask.send_file(os_path,conditional=True)
return response
Here's a quick and dirty implementation using pathlib's .iterdir and Flask.send_from_directory to create dynamic routes to files in the same directory as this flask app and generates a unordered list of links to be displayed at the root route.
This isn't recursive. It won't create routes for sub-directories or files within subdirectories. It's what I needed when I came looking here on SO for answers.
"""Simple Flask App to serve the contents of the current directory.
$ python serve_directory.py
this serves browseable contents of this file's directory.
to http://localhost:8080.
"""
from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING
from flask import Flask, send_from_directory
if TYPE_CHECKING:
from typing import Iterator
from flask import Response
# Instantiate a Flask app object
app: Flask = Flask(__name__)
# Get the parent directory of this script. (Global)
DIR_PATH: Path = Path(__file__).parent
def get_files_from_this_directory() -> Iterator[str]:
"""Generate the items within this script's directory.
Yields:
Generator: item(s) in __file__'s directory.
"""
for dir_item in DIR_PATH.iterdir():
yield dir_item.name
#app.route("/files/<file_name>") # type: ignore
def serve_file(file_name: str) -> Response:
"""Set up a dynamic routes for directory items at /files/.
Args:
file_name (str): regular file.
Returns:
Response: regular file.
"""
return send_from_directory(DIR_PATH, file_name)
def html_ul_of_items() -> str:
"""Create a unordered list of anchors/links to file routes.
Returns:
str: a <ul> with N <li> elements where N is the number of
elements in __file__'s directory.
"""
html: str = "<ul>"
for dir_item in get_files_from_this_directory():
html += f"<li><a href='files/{dir_item}'>{dir_item}</a`></li>"
return f"{html}</ul>"
#app.route("/") # type: ignore
def serve_index() -> str:
"""Root route which displays an unordered list of directory items.
Returns:
str: a <ul> with N <li> elements where N is the number of
elements in __file__'s directory.
"""
return html_ul_of_items()
def main() -> None:
"""Run the flask app."""
app.run(port=8080)
if __name__ == "__main__":
main()