如何使用Flask实现点击文件链接在网页查看文件内容?
问题分析与解决方案
你的代码存在几个关键问题,导致无法实现点击查看文件内容的功能:
- 直接使用本地文件路径作为链接
href,浏览器出于安全限制无法直接访问本地文件 - HTML结构拼接混乱,重复初始化、错误闭合标签,导致页面结构错乱
- 没有对应路由处理文件内容的请求
以下是修正后的完整代码:
from flask import Flask, render_template_string, abort import os from urllib.parse import quote app = Flask(__name__) BASE_FOLDER = "/home/user/" # 生成安全的文件路径,防止目录遍历攻击 def get_safe_path(file_path): full_path = os.path.abspath(os.path.join(BASE_FOLDER, file_path.lstrip('/'))) if not full_path.startswith(os.path.abspath(BASE_FOLDER)): return None return full_path @app.route("/") def mostrar_subcarpeta(): def generate_folder_html(root, depth=0): html = "" # 获取当前文件夹名称 folder_name = os.path.basename(root) if root != BASE_FOLDER else "根目录" # 缩进展示层级 html += f"<div style='margin-left: {depth*20}px;'>" html += f"<strong>{folder_name}</strong>" html += "<ul>" # 先处理文件 for filename in os.listdir(root): file_path = os.path.join(root, filename) if os.path.isfile(file_path): # 生成相对路径用于路由 rel_path = os.path.relpath(file_path, BASE_FOLDER) encoded_rel_path = quote(rel_path) html += f"<li><a href='/view/{encoded_rel_path}'>{filename}</a></li>" # 递归处理子文件夹 for folder in os.listdir(root): folder_path = os.path.join(root, folder) if os.path.isdir(folder_path): html += generate_folder_html(folder_path, depth+1) html += "</ul></div>" return html return render_template_string(""" <!DOCTYPE html> <html> <head> <title>文件浏览器</title> </head> <body> {{ folder_html|safe }} </body> </html> """, folder_html=generate_folder_html(BASE_FOLDER)) @app.route("/view/<path:file_path>") def view_file(file_path): safe_path = get_safe_path(file_path) if not safe_path or not os.path.isfile(safe_path): abort(404) # 根据文件类型读取内容,这里处理文本文件,其他类型可扩展 try: with open(safe_path, 'r', encoding='utf-8') as f: content = f.read() return render_template_string(""" <!DOCTYPE html> <html> <head> <title>查看文件: {{ filename }}</title> <style> pre { background: #f4f4f4; padding: 15px; overflow-x: auto; } </style> </head> <body> <h3>{{ filename }}</h3> <pre>{{ content }}</pre> <p><a href='/'>返回文件列表</a></p> </body> </html> """, filename=os.path.basename(safe_path), content=content) except UnicodeDecodeError: return "<h3>无法预览此文件:非文本格式</h3><p><a href='/'>返回文件列表</a></p>" if __name__ == "__main__": app.run(debug=True)
关键改进点:
- 安全路径处理:通过
get_safe_path函数限制访问范围在指定目录内,防止恶意目录遍历 - 正确路由链接:生成Flask内部路由
/view/来处理文件内容请求,不再直接使用本地路径 - 清晰的层级展示:递归生成带缩进的文件夹和文件结构,页面更易读
- 文本文件预览:支持UTF-8文本文件的内容展示,非文本文件给出提示
- 规范HTML结构:使用Jinja2模板渲染,避免手动拼接HTML的错误
内容的提问来源于stack exchange,提问作者leojim19
相关产品推荐
相关产品推荐

