如何在Flask(Python)中避免上传文件重名覆盖问题
Flask文件上传避免同名覆盖的解决方案
问题核心
你当前的代码直接使用原文件名保存文件,导致同名文件后传覆盖先传的情况。解决这个问题的核心是给每个上传文件生成全局唯一的保存文件名。
一、添加时间戳到文件名是否可行?
可行,但要注意时间精度:
- 如果只用秒级时间戳(比如
time.time()),同一秒内上传同名文件还是会冲突覆盖; - 改用毫秒/微秒级时间戳,冲突概率会大幅降低,但极端高并发场景下仍有理论可能;
- 更稳妥的方式是时间戳+随机唯一标识(比如UUID),彻底避免重复。
二、并发上传的问题解决
仅依赖时间戳的话,高并发场景下(比如同一毫秒有多个同名文件上传)还是存在覆盖风险。最可靠的方案是直接生成全局唯一的文件名,比如结合「UUID+原文件名扩展名」——UUID本身是全局唯一的,完全不用担心重复。
修改后的代码实现
以下是调整后的app.py代码,重点修改了文件保存的逻辑:
from flask import Flask, redirect, url_for, render_template, request from werkzeug.utils import secure_filename import os import uuid # 用于生成唯一ID from datetime import datetime app = Flask(__name__) app.config['UPLOAD_FOLDER'] = "D:/Me/FlaskProject/uploads" @app.route('/upload') def upload(): return render_template("upload.html", page="Upload Images") @app.route('/upload_complete', methods = ['GET', 'POST']) def upload_complete(): if request.method == 'POST': f = request.files['file'] # 安全处理原文件名,拆分名称与扩展名 original_filename = secure_filename(f.filename) name, ext = os.path.splitext(original_filename) # 生成唯一文件名:两种可选方式 # 方式1:仅UUID+扩展名(最简洁可靠) unique_filename = f"{uuid.uuid4().hex}{ext}" # 方式2:时间戳+UUID+扩展名(保留上传时间信息) # timestamp = datetime.now().strftime("%Y%m%d%H%M%S%f") # unique_filename = f"{timestamp}_{uuid.uuid4().hex}{ext}" # 拼接保存路径并写入文件 save_path = os.path.join(app.config['UPLOAD_FOLDER'], unique_filename) f.save(save_path) return redirect(url_for('upload_complete')) return render_template("upload_complete.html", page="Upload Complete") if __name__ == '__main__': app.debug = True app.run()
代码说明
secure_filename:必须保留,用于过滤原文件名中的危险字符(比如路径分隔符),避免目录遍历攻击;- UUID生成:
uuid.uuid4().hex会生成32位十六进制唯一字符串,确保文件名绝对不重复; - 保留扩展名:拆分原文件名的扩展名,保证保存后的文件仍能被识别类型;
- 可选时间戳:如果需要记录上传时间,可以将时间戳加入文件名,方便后续文件管理。
你的项目结构
FlaskProject: ├───static ├───templates ├───uploads └───app.py
上传页面HTML代码(无需修改)
{%extends "base.html" %} {%block content%} <p> <h2>Upload Below!</h2> <div></div> <form action = "http://localhost:5000/upload_complete" method = "POST" enctype = "multipart/form-data"> <input type = "file" name = "file" /> <input type = "submit"/> </form> {% endblock %}
内容的提问来源于stack exchange,提问作者Tigereagle12345
相关产品推荐
相关产品推荐

