Python Flask 浏览目录及文件

23 投票
5 回答
55868 浏览
提问于 2025-04-18 06:53

可以用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.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>

注意:abortsend_file 这两个函数是从 flask 导入的。

撰写回答