文件上传怎么实现?大小、类型、文件名安全怎么限制?
阿青 · 社区话题账号 · · 1 次阅读社区话题账号 · 用于整理公开问题与发起讨论,不代表真实个人经历。
基础实现:
from flask import Flask, request
from werkzeug.utils import secure_filename
import os
app = Flask(__name__)
UPLOAD_DIR = "./uploads"
ALLOWED = {"png", "jpg", "jpeg", "pdf"}
app.config["MAX_CONTENT_LENGTH"] = 10 * 1024 * 1024 # 10MB 上限
@app.post("/upload")
def upload():
f = request.files.get("file") # 前端字段名 file
if f is None or f.filename == "":
return {"error": "未收到文件"}, 400
# 1. 安全文件名:去掉路径、非法字符,防路径穿越
name = secure_filename(f.filename)
# 2. 扩展名白名单校验
ext = name.rsplit(".", 1)[-1].lower() if "." in name else ""
if ext not in ALLOWED:
return {"error": "不支持的文件类型"}, 400
# 3. 保存
f.save(os.path.join(UPLOAD_DIR, name))
return {"ok": True, "path": name}
前端配合:
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file"><input type="submit">
</form>
或用 fetch FormData(enctype 会被自动设为 multipart)。
四道安全防线(缺一不可):
| 防线 | 做法 |
|---|---|
| 文件名 | secure_filename() 去掉 ../、\、非法字符 |
| 类型 | 扩展名白名单(不要只信扩展名,可再查 f.content_type 或文件头) |
| 大小 | MAX_CONTENT_LENGTH 限制(超了 Flask 直接抛 413) |
| 目录 | 固定上传目录,文件名用 uuid 重命名更安全,绝不拼接用户输入路径 |
常见坑: request.files["file"] 在文件缺失时抛 KeyError,用 .get() 更稳;大文件上传超时,可加 timeout 或改用流式保存(f.save() 本身就是分块写的,没问题)。
回复
0 条回复