Files
abot/admin/dashboard/blueprints/file_browser.py
2025-06-04 17:52:41 +08:00

113 lines
3.6 KiB
Python

from flask import Blueprint, render_template, jsonify, send_file, request
import os
from loguru import logger
file_browser_bp = Blueprint('file_browser', __name__)
@file_browser_bp.route('/file_browser')
def file_browser():
"""文件浏览器页面"""
return render_template('file_browser.html')
@file_browser_bp.route('/api/list_files')
def list_files():
"""获取指定目录下的文件列表"""
try:
path = request.args.get('path', '')
# 获取项目根目录
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
# 构建完整路径
full_path = os.path.join(project_root, path)
# 安全检查:确保路径在项目根目录内
if not os.path.abspath(full_path).startswith(project_root):
return jsonify({"success": False, "message": "访问被拒绝:路径超出项目范围"})
if not os.path.exists(full_path):
return jsonify({"success": False, "message": "目录不存在"})
# 需要隐藏的目录列表
hidden_dirs = {
'__pycache__',
'.git',
'.idea',
'.venv',
'venv',
'env',
'node_modules',
'.vscode',
'.pytest_cache',
'.coverage',
'htmlcov',
'dist',
'build',
'.eggs',
'*.egg-info'
}
items = []
for item in os.listdir(full_path):
# 跳过隐藏文件和目录
if item.startswith('.'):
continue
item_path = os.path.join(full_path, item)
is_dir = os.path.isdir(item_path)
# 跳过隐藏目录
if is_dir and item in hidden_dirs:
continue
items.append({
"name": item,
"is_dir": is_dir,
"size": os.path.getsize(item_path) if not is_dir else 0,
"modified": os.path.getmtime(item_path)
})
# 对文件列表进行排序:目录在前,同类型按名称排序
items.sort(key=lambda x: (not x["is_dir"], x["name"].lower()))
return jsonify({
"success": True,
"data": {
"items": items,
"current_path": path
}
})
except Exception as e:
logger.error(f"列出文件失败: {e}")
return jsonify({"success": False, "message": str(e)})
@file_browser_bp.route('/api/download_file')
def download_file():
"""下载指定文件"""
try:
path = request.args.get('path', '')
# 获取项目根目录
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
# 构建完整路径
full_path = os.path.join(project_root, path)
# 安全检查:确保路径在项目根目录内
if not os.path.abspath(full_path).startswith(project_root):
return jsonify({"success": False, "message": "访问被拒绝:路径超出项目范围"})
if not os.path.exists(full_path):
return jsonify({"success": False, "message": "文件不存在"})
if os.path.isdir(full_path):
return jsonify({"success": False, "message": "不能下载目录"})
return send_file(
full_path,
as_attachment=True,
download_name=os.path.basename(full_path)
)
except Exception as e:
logger.error(f"下载文件失败: {e}")
return jsonify({"success": False, "message": str(e)})