Python Flask 浏览目录及文件
可以用Flask来浏览一个包含文件的目录吗?
我的代码总是出问题,字符串之间会出现奇怪的拼接。
另外,我也不知道怎么检查一个路径是文件还是文件夹。
这是我的Flask应用的路由:
@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)
这是我的HTML模板,如果有人能给我一些建议,我会非常感激!
<body>
<h2>Files {{ currdir }}</h2> </br>
{% for name in files: %}
<A HREF="{{ directory }}{{ name }}">{{ name }}</A> </br></br>
{% endfor %}
</body>s.html',files=files,directory=basedir + directory,currdir=directory)
5 个回答
0
试试这个 send_from_directory
:
from flask import send_from_directory
@app.route('/my_folder/<filename>')
def my_files(filename):
return send_from_directory("my_folder", filename)
0
这里有一个简单粗暴的实现,使用了 pathlib
的 .iterdir
方法和 Flask.send_from_directory
来创建动态路由,这些路由指向与这个 Flask 应用在同一目录下的文件,并生成一个无序列表的链接,显示在根路由上。
这个实现并不是递归的。也就是说,它不会为子目录或子目录中的文件创建路由。当我在 Stack Overflow 上寻找答案时,这正是我需要的。
"""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()
1
我为我的项目创建了这个功能……它运行得非常好……它从这个文件夹开始浏览:/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><a href="../">../</a>\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 += '<a href="' + file + '/">' + file + '/</a>'+spaces1+date+spaces2+' -\n'
else: html += '<a href="' + file + '">' + file + '</a>'+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
9
这里有一个可以运行的例子。
# 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()
这里有一个可以用的代码库
31
在网址结构中,使用一个 path
转换器(可以参考这个文档)比把所有可能的路径结构写死要好。
可以用 os.path.exists
来检查路径是否有效,而 os.path.isfile
和 os.path.isdir
则分别用来检查这个路径是文件还是文件夹。
接口:
@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)
模板(现在可以浏览目录啦 :)):
<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>
注意:abort
和 send_file
这两个函数是从 flask 导入的。