
本文讲解如何在 Flask 应用中,将前端页面中动态生成的文件名(而非固定按钮值)准确、安全地传递至删除路由,避免硬编码表单字段和潜在的键名冲突问题。核心方案是使用 Flask 的变量路由()配合 url_for() 构建带参提交链接。
本文讲解如何在 flask 应用中,将前端页面中动态生成的文件名(而非固定按钮值)准确、安全地传递至删除路由,避免硬编码表单字段和潜在的键名冲突问题。核心方案是使用 flask 的变量路由(`
在 Flask 开发中,常见需求是为列表项(如视频文件)提供独立操作按钮(例如“删除”),而每个按钮需关联其对应的具体资源(如文件名)。原始代码试图通过 提交循环索引,但 request.form['idx'] 实际获取的是按钮的 value(即字符串 "Delete"),而非预期的索引或文件名——根本原因在于 name="idx" 是静态字符串,未绑定循环变量。
更可靠、更符合 Web 最佳实践的方案是:将文件名作为 URL 路径参数直接嵌入删除表单的 action 地址中。这无需依赖表单数据解析,规避了 name 冲突、空值风险与 XSS 潜在隐患,同时语义清晰、调试直观。
以下是重构后的完整实现:
from flask import Flask, redirect, render_template_string, url_for
import os
app = Flask(__name__)
@app.route('/archive')
def archive():
path = '/home/pi/Videos/'
try:
dir_list = sorted(os.listdir(path)) # 安全读取并排序
except OSError as e:
return f"Error accessing directory: {e}", 500
# 使用 Jinja2 模板字符串渲染动态页面
html_template = '''
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Video Archive</title></head>
<body>
<div class="box">
<div class="flex-box">
{% for file in dir_list %}
<div style="background: #1a1a1a; color: #fff; padding: 12px; margin: 4px 0; border-radius: 4px;">
<strong>{{ file }}</strong>
<form method="post" action="{{ url_for('delete', filename=file) }}" style="display:inline;margin-left:12px;">
<button type="submit" class="btn" style="background:#e74c3c;color:white;border:none;padding:6px 12px;border-radius:4px;cursor:pointer;">
Delete
</button>
</form>
</div>
{% else %}
<p>No videos found.</p>
{% endfor %}
</div>
</div>
</body>
</html>
'''
return render_template_string(html_template, dir_list=dir_list)
@app.post('/delete/<path:filename>')
def delete(filename):
base_path = '/home/pi/Videos/'
full_path = os.path.join(base_path, filename)
# 关键安全校验:防止路径遍历攻击(如 filename="../../etc/passwd")
if not os.path.abspath(full_path).startswith(os.path.abspath(base_path)):
return "Invalid file path", 400
try:
if os.path.isfile(full_path):
os.remove(full_path)
else:
return f"File not found: {filename}", 404
except PermissionError:
return f"Permission denied: {filename}", 403
except Exception as e:
return f"Error deleting {filename}: {e}", 500
return redirect(url_for('archive'))✅ 关键改进说明:
-
路径参数替代表单字段:/delete/
直接捕获文件名,url_for('delete', filename=file) 自动生成合法 URL,无需解析 request.form。 - <...><...>











