Is it possible to serve not a index of a directory but rather an html file using Python SimpleHTTPServer on path '/'?
Having directory with one file login.html serves a directory index on path '/'.
python -m SimpleHTTPServer 7800
I want a content of login.html on '/'.
Is that possible?
SimpleHTTPServer (or http.server in Python3) will serve a directory unless that directory contains a file called index.html, in which case it will serve that instead.
So just rename login.html to index.html and it should do what you want.
By default http server looks for index.html file and loads it. Otherwise it will serve the directory structure.
You can extend SimpleHTTPServer and write your own class with proper routing. I would prefer this.
But alternatively you could also add a redirect in index.html.
<html>
<body>
<!-- redirect on load -->
<script>
window.onload = function () {
window.location.href = "login.html";
}
</script>
</body>
</html>
Related
I am working on a flask based UI and there I am downloading a text file using send_file function.
This is my directory setup:
/static
/design.css
/templates
/index.html
/upload.html
/engine.html
/output
/text_file.txt
/main.py
Below is the code:
#app.route('/download')
def download_file():
path = "output\\text_file.txt"
return send_file(path, as_attachment=True)
And below is related html button which is initiating the download:
<button>
<a href="{{ url_for('.download_file') }}" style="color: white; text-decoration: none;">Download Source Text
</a>
</button>
Now this function is directly downloading the file in downloads folder of my local C drive. But I want to get an option to select the location like below:
(image taken from google)
How can I achieve this?
The path to save the downloaded file is decided by a browser and server-side application cannot change this--and this is a feature, not a bug.
You think about it--say a server application can pick a location to save a file, what if my website saves an exe file to your C:\Windows folder? The consequence is disastrous...
Some modern browsers allow users to set a default download path. If you discover that your file is saved to a folder, such as Downloads, without asking you, most likely you have this browser feature enabled.
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?
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 am running a Flask app where the user uploads a file and must select the root folder path of where to upload the file on a network drive. This path is an IIS available network path and is also a network drive on all user's computers.
I want to dynamically show the available folders in HTML, even if new folders are created after the app starts.
I know this can't be done with pure HTML due to security but wanted to know if there was a way around this with Flask. The goal is to use Python to move the upload file to the choosen folder path.
I have tried:
<form><input type="file" name=dir webkitdirectory directory multiple/></form>
But this only works in Chrome. With the path choosen by the user I can pass this onto Python to copy the upload file to there.
Due to modern browser limitations I decided to use JSTree as a solution. And it is working very well. It features a tree structure browser. The structure is the result of outputting the folders as JSON. You can add a search bar as well so the user can just type in a folder name to search.
Please see JSTree https://www.jstree.com/
How to implement this with Flask
HTML/JS:
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css">
<div>
<input class="search-input form-control" placeholder="Search for folder"></input>
</div>
<script id="jstree1" name="jstree1">
/*Search and JS Folder Tree*/
$(function () {
$(".search-input").keyup(function () {
var searchString = $(this).val();
console.log(searchString);
$('#container').jstree('search', searchString);
});
$('#container').jstree({
'core': {
"themes": {
"name": "default"
, "dots": true
, "icons": true
}
, 'data': {
'url': "static/JSONData.json"
, 'type': 'GET'
, 'dataType': 'JSON'
}
}
, "search": {
"case_insensitive": true
, "show_only_matches": true
}
, "plugins": ["search"]
});
});
{ /* --- THIS IS FOLDER SELECTOR FOR ID "folderout" --- */
$("#container").on("select_node.jstree", function (evt, data) {
var number = data.node.text
document.getElementById("folderout").value = number;
});
In Flask/WTForms call on the id "folderout". This will return the path to WTForms when the user clicks the folder.
folderout = TextField('Folder:', validators=[validators.required()])
To Create the JSON JStree File using Python:
import os
# path : string to relative or absolute path to be queried
# subdirs: tuple or list containing all names of subfolders that need to be
# present in the directory
def all_dirs_with_subdirs(path, subdirs):
# make sure no relative paths are returned, can be omitted
path = os.path.abspath(path)
result = []
for root, dirs, files in os.walk(path):
if all(subdir in dirs for subdir in subdirs):
result.append(root)
return result
def get_directory_listing(path):
output = {}
output["text"] = path.decode('latin1')
output["type"] = "directory"
output["children"] = all_dirs_with_subdirs(path, ('Maps', 'Reports'))
return output
with open('test.json', 'w+') as f:
listing = get_directory_listing(".")
json.dump(listing, f)
Python runs on your server, therefoere it will not be possible to use that to move the files on the client side. If you think about it, let's assume you manage to somehow (magically) send python commands to the clients to move files, do you know if they even have python installed to be able to interpret your commands?
Javascript on the other hand is running on client side and was used to achieve this. However, like you said, due to security reasons modern browswers won't allow that. If they would allow it then any website could potentially see your whole File System.
Here is an article that explains a bit why. Look up the File Upload Control section of it. Hope this makes things a bit clearer.
EDIT: after seeing your comment you could achieve that using os.walk. Beware it could be slow.
for root, dirs, files in os.walk(rootPath): # for example "C:/Users/"
for file in files:
if file == (wantedFile):
print(os.path.join(root,file))
break
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.