Chat
Ask me anything
Ithy Logo
Sign in to save

使用 Python Flask 0.12.2 创建文件上传按钮的完整指南

一步步实现用户点击上传按钮后将本地文件上传到服务器的功能

file upload concept

关键要点

  • HTML 表单的正确配置:确保表单的 `enctype` 属性设置为 `multipart/form-data`。
  • Flask 后端处理:使用适当的路由和安全函数处理文件上传。
  • 安全性措施:通过 `secure_filename` 函数和文件类型限制提升上传安全性。

项目设置与环境配置

安装 Flask 0.12.2

首先,确保你已经安装了 Flask 0.12.2。如果尚未安装,可以使用以下命令通过 pip 安装指定版本的 Flask:

pip install Flask==0.12.2

项目结构

建议采用以下项目结构来组织你的 Flask 应用:

目录/文件 说明
app.py 主 Flask 应用文件
templates/ 存放 HTML 模板文件
uploads/ 存放上传的文件

创建 HTML 上传表单

上传表单的基本结构

在 `templates` 目录下创建一个 `upload.html` 文件,并添加以下内容:

<form action="{{ url_for('upload_file') }}" method="post" enctype="multipart/form-data">
    <input type="file" name="file" accept=".txt,.pdf,.png,.jpg,.jpeg,.gif" required>
    <input type="submit" value="上传">
</form>

关键点:

  • `method` 必须设置为 `post`。
  • `enctype` 必须设置为 `multipart/form-data`,以支持文件上传。
  • `input type="file"` 创建文件选择按钮,并通过 `accept` 属性限制文件类型。

Flask 后端处理文件上传

配置上传目录

在 `app.py` 中,配置一个用于存储上传文件的目录:

import os
from flask import Flask, render_template, request, redirect, url_for, flash
from werkzeug.utils import secure_filename

app = Flask(__name__)
app.secret_key = 'your_secret_key'  # 用于会话管理

# 设置上传文件的保存目录
UPLOAD_FOLDER = os.path.join(os.getcwd(), 'uploads')
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

# 允许上传的文件类型
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}

# 确保上传目录存在
if not os.path.exists(UPLOAD_FOLDER):
    os.makedirs(UPLOAD_FOLDER)

文件类型验证函数

为了提高安全性,定义一个函数来验证文件的扩展名:

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

定义路由处理上传

在 `app.py` 中,定义路由来显示上传表单和处理文件上传请求:

@app.route('/')
def index():
    return render_template('upload.html')

@app.route('/upload', methods=['POST'])
def upload_file():
    # 检查是否有文件部分
    if 'file' not in request.files:
        flash('没有文件部分')
        return redirect(request.url)
    
    file = request.files['file']
    
    # 如果用户没有选择文件,浏览器也可能提交一个空的部分
    if file.filename == '':
        flash('未选择文件')
        return redirect(url_for('index'))
    
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
        flash('文件上传成功')
        return redirect(url_for('index'))
    else:
        flash('文件格式不允许')
        return redirect(url_for('index'))

说明:

  • 使用 `request.files` 获取上传的文件。
  • 通过 `secure_filename` 函数处理文件名,防止路径遍历攻击。
  • 使用 `flash` 显示提示消息,需在模板中处理显示。

模板中的消息显示

在 HTML 模板中显示闪现消息

修改 `upload.html`,添加用于显示提示信息的部分:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>文件上传示例</title>
</head>
<body>
    <h1>上传文件</h1>
    
    <!-- 显示提示消息 -->
    {% with messages = get_flashed_messages() %}
      {% if messages %}
        <ul>
        {% for message in messages %}
          <li>{{ message }}</li>
        {% endfor %}
        </ul>
      {% endif %}
    {% endwith %}
    
    <!-- 上传表单 -->
    <form action="{{ url_for('upload_file') }}" method="post" enctype="multipart/form-data">
        <input type="file" name="file" accept=".txt,.pdf,.png,.jpg,.jpeg,.gif" required>
        <input type="submit" value="上传">
    </form>
    
</body>
</html>

运行与测试应用

启动 Flask 应用

在命令行中运行以下命令启动 Flask 应用:

python app.py

确保终端显示类似下面的信息,表明 Flask 服务器已启动:

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!

测试文件上传功能

打开浏览器,访问 http://127.0.0.1:5000/ ,你将看到上传表单。选择文件并点击上传按钮,上传结果会在页面上显示相应的提示消息。


安全性与最佳实践

限制文件大小

为了防止用户上传过大的文件,可以在 Flask 配置中设置最大文件大小:

# 限制上传文件大小为 16MB
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024

超过此限制的文件将被 Flask 拒绝上传。

限制文件类型

通过前文的 `ALLOWED_EXTENSIONS` 集合和 `allowed_file` 函数,确保只允许上传特定类型的文件,提升应用安全性。

使用 `secure_filename` 函数

使用 `secure_filename` 函数处理上传文件的文件名,防止恶意用户通过文件名进行路径遍历攻击。

处理错误与异常

在生产环境中,建议添加更多的错误处理机制,确保应用在出现异常时不会暴露敏感信息。同时,可以记录上传日志以便后续审查。


完整示例代码

app.py

import os
from flask import Flask, render_template, request, redirect, url_for, flash
from werkzeug.utils import secure_filename

app = Flask(__name__)
app.secret_key = 'your_secret_key'  # 用于会话管理

# 设置上传文件的保存目录
UPLOAD_FOLDER = os.path.join(os.getcwd(), 'uploads')
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

# 允许上传的文件类型
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}

# 确保上传目录存在
if not os.path.exists(UPLOAD_FOLDER):
    os.makedirs(UPLOAD_FOLDER)

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/')
def index():
    return render_template('upload.html')

@app.route('/upload', methods=['POST'])
def upload_file():
    # 检查是否有文件部分
    if 'file' not in request.files:
        flash('没有文件部分')
        return redirect(request.url)
    
    file = request.files['file']
    
    # 如果用户没有选择文件,浏览器也可能提交一个空的部分
    if file.filename == '':
        flash('未选择文件')
        return redirect(url_for('index'))
    
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
        flash('文件上传成功')
        return redirect(url_for('index'))
    else:
        flash('文件格式不允许')
        return redirect(url_for('index'))

if __name__ == '__main__':
    app.run(debug=True)

templates/upload.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>文件上传示例</title>
</head>
<body>
    <h1>上传文件</h1>
    
    <!-- 显示提示消息 -->
    {% with messages = get_flashed_messages() %}
      {% if messages %}
        <ul>
        {% for message in messages %}
          <li>{{ message }}</li>
        {% endfor %}
        </ul>
      {% endif %}
    {% endwith %}
    
    <!-- 上传表单 -->
    <form action="{{ url_for('upload_file') }}" method="post" enctype="multipart/form-data">
        <input type="file" name="file" accept=".txt,.pdf,.png,.jpg,.jpeg,.gif" required>
        <input type="submit" value="上传">
    </form>
    
</body>
</html>

扩展功能与优化

文件类型扩展

根据需要,可以扩展 `ALLOWED_EXTENSIONS` 集合,允许更多或更少的文件类型上传。

使用 Flask-Uploads 插件

为了更方便地管理上传文件,可以考虑使用 Flask-Uploads 插件,它提供了更为丰富的功能和更简洁的 API。

前端增强

可以使用 JavaScript 或前端框架来增强用户体验,例如显示上传进度条、预览文件等。


结论

通过上述步骤,你可以在 Flask 0.12.2 应用中创建一个功能完善且安全的文件上传按钮。确保遵循最佳实践,例如限制文件类型和大小,并使用 `secure_filename` 函数来处理上传文件的文件名。进一步的优化和功能扩展可以根据具体需求进行调整,以提升用户体验和应用安全性。


参考资料

pallet.readthedocs.io
Flask 文件上传文档
tutorialspoint.com
Flask 文件上传教程


Last updated February 7, 2025

AI-assisted research. Sources, methodology and corrections · Source-checked guides and tools · Explore published answers

Ask Ithy AI
Download Article
Delete Article