gmaksimнабросал простой рабочий вариант
результат
app.py
import os
from functools import wraps
from flask import Flask, render_template, send_file, abort
app = Flask(__name__)
app.debug = True
TOP_DIR = app.root_path
def normalize_path(path, follow_symlinks=True):
# resolves symbolic links
if follow_symlinks:
return os.path.realpath(path)
return os.path.abspath(path)
def is_safe_path(basedir, path):
return path.startswith(basedir)
def check_and_transform_path(f):
@wraps(f)
def wrapper(*args, **kwargs):
path = normalize_path(kwargs.get("path", TOP_DIR))
if not is_safe_path(TOP_DIR, path) or not os.path.exists(path):
abort(404)
kwargs["path"] = path
return f(*args, **kwargs)
return wrapper
@app.route('/')
@app.route('/<path:path>')
@check_and_transform_path
def dir_viewer(path=None):
entries = os.scandir(path)
prev_dir = None
if path and path != TOP_DIR:
prev_dir = os.path.relpath(os.path.dirname(path), TOP_DIR)
return render_template("list.html", entries=entries,
prev_dir=prev_dir)
@app.route("/download/<path:path>")
@check_and_transform_path
def download(path):
return send_file(path)
if __name__ == '__main__':
app.run()
templates/list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
{% if prev_dir %}
<li><a href="{{ url_for("dir_viewer", path=prev_dir) }}">..</a></li>
{% endif %}
{% for entry in entries %}
<li>
{% if entry.is_file() %}
<a href="{{ url_for("download", path=entry.path) }}">{{ entry.name }}</a>
{% else %}
<a href="{{ url_for("dir_viewer", path=entry.path) }}">{{ entry.name }}</a>
{% endif %}
</li>
{% endfor %}
</ul>
</body>
</html>
прикрепляю еще архив с этими файлами