Python Flask浏览包含文件的目录

22

能否使用Flask浏览含文件的目录?

我的代码似乎从未正确工作,字符串间出现了奇怪的追加。

此外,我不知道如何实现一种检查路径是文件还是文件夹的方法。

这是我的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)

以下是我的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个回答

29
在url结构中使用path转换器(文档链接)比硬编码所有可能的路径结构更好。
可以使用os.path.exists检查路径是否有效,使用os.path.isfileos.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导入的。

谢谢,它有点起作用。然而我遇到的问题是有时候URL中的“/”没有正确地附加上去。 - user2882307
我编写了上面的代码作为起点。你可以添加逻辑来检查路径是否是目录,然后使用os.path.isdir来添加/ - vivekagr

8
这里有一个可行的例子。
# 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()

以下是一个可用的代码库:


我尝试使用简单的Dockerfile暴露5000端口,但输出为“127.0.0.1没有发送任何数据。ERR_EMPTY_RESPONSE”。你有什么想法,我可能错过了什么吗? - Prathamesh dhanawade
@Prathameshdhanawade 不确定,伙计。不过我在写这个程序时已经在我的Windows笔记本上尝试过了。如果你愿意,可以先在本地系统上使用虚拟环境进行尝试,然后再将其容器化。 - Gajendra D Ambi

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

1
这是一场即将发生的灾难。 - miken32

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.iterdirFlask.send_from_directory 来创建动态路由到与该 Flask 应用程序相同目录中的文件,并生成无序链接列表,在根路由处显示。

这不是递归的。它不会为子目录或子目录中的文件创建路由。当我在 SO 上寻找答案时,这就是我需要的东西。

"""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()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接