Найти - Пользователи
Полная версия: Flask Просмотр локальной папки в браузере, работа с файлами
Начало » Web » Flask Просмотр локальной папки в браузере, работа с файлами
1 2
gmaksim
Пытаюсь сделать небольшой просмотрщик файлов и папок (с возможностью удаления, скачивания, загрузки, навигации по папкам) работающий в веб-браузере. Судя по всему при использовании Python, для этих целей более всего подходит Flask.
Удалось путем чтения туториалов и стековерфлоу реализовать следующее (загрузка файлов и просмотр папки, куда все загружается):
 import os
from flask import request, redirect, url_for, render_template, abort, send_file
from werkzeug.utils import secure_filename
from app import app
@app.route('/')
@app.route('/index/')
def index():
    path = os.path.expanduser('static')
    return render_template('index.html', tree=make_tree(path))
def make_tree(path):
    tree = dict(name=path, children=[])
    try: lst = os.listdir(path)
    except OSError: pass
    else:
        for name in lst:
            fn = os.path.join(path, name)
            if os.path.isdir(fn):
                tree['children'].append(make_tree(fn))
            else:
                tree['children'].append(dict(name=fn))
    return tree
UPLOAD_FOLDER = 'static'
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def make_dirs():
    # os.mkdir('static')
    # os.mkdir('tmp')
    # os.mkdir('app')
    # os.mkdir('app/templates')
    # os.mkdir('app/static')
    pass
def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('//', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        if 'file' not in request.files:
            flash('No file part')
            return redirect(request.url)
        file = request.files['file']
        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('index'))
    return
 <html>
  <head>
<title>Path: {{ tree.name }}</title>
<h1>{{ tree.name }}</h1>
  </head>
  <body>
       <form method=post enctype=multipart/form-data>
      <input type=file name=file>
         <input type=submit value=Upload>
    </form>
<ul>
{%- for item in tree.children recursive %}
    <li><a href="{{ item.name }}">{{ item.name }}</a>
    {%- if item.children -%}
      <ul><a href="/static/{{ (item.children) }}">{{ loop(item.children) }}</a></ul>
    {%- endif %}</li>
{%- endfor %}
</ul>
  </body>
</html>
Но минус в том, что выводится просто большой список всего, что есть в заданном основном каталоге, что не дает возможность навигации и тд и тп. Плюс не понятно как сделать возможность скачивания и всего остального в такой ситуации.
Возможно есть примеры схожих небольших проектов (находил похожее на github, но простыми и легкими их сложно назвать), как пример. Или какой-либо другой возможный путь реализации задумки.

Спасибо!
JOHN_16
gmaksim
Судя по всему при использовании Python, для этих целей более всего подходит Flask.
интересное утверждение, как вы к нему пришли?
А я для подобного брал iohttp. А на заре использовал обычный BaseHttpServer или как там он во втором питоне назывался.
gmaksim
JOHN_16
интересное утверждение, как вы к нему пришли?
google.ru + ya.ru
JOHN_16
я для подобного брал iohttp.
JOHN_16
на заре использовал обычный BaseHttpServer
Первое не сталкивался, надо посмотреть.
Второе пробовал, но никак в толк не могу взять как это все вязать с HTTP, как-то слишком странно выглядит, честно говоря, неужели так делают?
Если у вас есть примеры кода (старого) или какой-либо реализации не на Flask/модной библиотеке, буду дичайше благодарен.
sander
gmaksim
упрощенный вариант с навигацией

 @app.route("/<paht:path>")
def dir_viewer(path):
    entries = os.scandir(path)
    # тут нормальный шаблон с render_template
    return """{% for entry in entries %}
       {% if entry.is_file() %}
            <a href="{{ url_for("download_file", path=entry.path) }}">{{ entry.name }}</a>
        {% else %}
            <a href="{{ url_for("dir_viewer", path=entry.path) }}">{{ entry.name }}</a>
        {% endif %}
      {% endfor %}
       """
@app.route("/download/<path:path>")
def download_file(path):
    return send_file(path)
       
gmaksim
sander
Не удается воспользоваться, что-то не так в строчках
  <a href="{{ url_for("download_file", path=entry.path) }}">{{ entry.name }}</a>
 <a href="{{ url_for("dir_viewer", path=entry.path) }}">{{ entry.name }}</a>
Когда убираешь кавычки у названий функций, возникает новая ошибка:
ValueError: View function did not return a response
Попробую разобраться сейчас.

Еще кажется тут должно быть path:path:
 @app.route("/<paht:path>")
Или нет?
sander
gmaksim
Не удается воспользоваться, что-то не так в строчках
если есть ошибка - кидай трейсбек.

gmaksim
Еще кажется тут должно быть path:path:
опечатка, да.
gmaksim
Не получается все равно воспользоваться, что вы подразумевается под нормальным шаблоном с render_template?
Данный код судя по всему в действующий не включить? Переход на /download/ тут:
 @app.route("/download/<path:path>")
def download_file(path):
совсем не понимаю. Точнее сам download - это будет работать в виду перехода на url в адресной строке и дальше автоматически подставляться в зависимости от того, что мы выбрали?
sander
gmaksim
gmaksim
Не получается все равно воспользоваться, что вы подразумевается под нормальным шаблоном с render_template?
файл с html шаблоном, который рендерится через вызов render_template
gmaksim
Точнее сам download - это будет работать в виду перехода на url в адресной строке и дальше автоматически подставляться в зависимости от того, что мы выбрали?
все что идет после “/download/” будет считаться путем к файлу
gmaksim
sander
файл с html шаблоном, который рендерится через вызов render_template
Т.е. после включения части
 {% for entry in entries %}
       {% if entry.is_file() %}
            <a href="{{ url_for("download_file", path=entry.path) }}">{{ entry.name }}</a>
        {% else %}
            <a href="{{ url_for("dir_viewer", path=entry.path) }}">{{ entry.name }}</a>
        {% endif %}
      {% endfor %}
В html файл, на который ссылается вызов render_template должны в месте добавления этой части отображаться файлы?
sander
gmaksim
да, если сделаешь
 render_template("<template name>.html", entries=entries)
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB