You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flask中实现支持多次点击的图片连续旋转功能

问题原因分析

你的代码无法连续旋转的核心原因是:每次POST请求处理时,都会重新拉取原始图片,且没有记录上一次的旋转状态,所以每次旋转都是基于原始图操作,重复点击同一个按钮时,旋转后的结果和上一次完全一致,看起来就像没有生效。
额外注意:确保你的两个旋转按钮放在<form method="POST">标签内,否则点击按钮不会正常提交POST请求

最优解决方案:使用Session存储累计旋转角度(推荐)

该方案无需传输大容量的base64图片数据,也不会因为多次旋转产生画质损失,性能最优。

步骤1:配置Flask Session密钥

首先在你的Flask应用初始化代码中添加Session配置,否则无法正常使用Session:

from flask import Flask, session, request, render_template
import requests
from PIL import Image
from io import BytesIO
import io
import base64

app = Flask(__name__)
# 替换为你自己的随机密钥
app.config['SECRET_KEY'] = 'your_custom_secret_key_here'

步骤2:修改index路由逻辑

@app.route('/', methods=['GET', 'POST'])
def index():
    original_image_url = "https://cdn.pixabay.com/photo/2017/09/25/13/12/cocker-spaniel-2785074__340.jpg"
    # 预加载原始图
    response = requests.get(original_image_url)
    original_img = Image.open(BytesIO(response.content))

    if request.method == 'GET':
        # 首次访问初始化旋转角度为0
        session['rotate_angle'] = 0
        # 原始图转base64返回
        data = io.BytesIO()
        original_img.save(data, "PNG")
        encoded_img = base64.b64encode(data.getvalue()).decode('utf-8')
        return render_template("index.html", image=encoded_img)
    
    if request.method == 'POST':
        # 获取当前累计旋转角度
        current_angle = session.get('rotate_angle', 0)
        # 根据点击的按钮更新角度
        if request.form.get('right_button') is not None:
            current_angle += 90
        elif request.form.get('left_button') is not None:
            current_angle -= 90
        # 角度取模,避免数值无限增长
        current_angle = current_angle % 360
        session['rotate_angle'] = current_angle

        # 直接基于原始图旋转总角度,避免多次旋转画质损失
        # 加expand=True防止旋转后图片被裁剪
        rotated_img = original_img.rotate(current_angle, expand=True)
        # 转base64
        data = io.BytesIO()
        rotated_img.save(data, "PNG")
        encoded_rotated_img = base64.b64encode(data.getvalue()).decode('utf-8')
        return render_template("index.html", image=encoded_rotated_img)

步骤3:优化说明

你原有代码中的check_rotate函数可以直接整合到路由逻辑中,不需要单独拆分,也不需要每次传入img对象处理。如果有其他编辑逻辑需要拆分也可以自行调整。

替代方案:前端隐藏字段存储状态(无Session场景)

如果你的场景不适合用Session(比如需要支持无状态部署),可以在前端表单中添加隐藏字段存储当前旋转角度:

  1. 前端模板form标签内添加:
<input type="hidden" name="current_angle" value="{{current_angle}}">
  1. 后端POST时读取request.form.get('current_angle', 0)更新角度后,再把新的角度传回模板渲染即可。
可选方案:传输当前编辑后的图片(多编辑操作场景)

如果你的功能后续还要加裁剪、滤镜等其他编辑操作,需要基于上一次修改后的图片操作,可以把当前base64图片存在前端隐藏字段中,POST时传到后端解码后再做编辑,不过该方案每次请求要传输大容量的base64数据,性能低于角度存储方案。

注意:Pillow的rotate方法默认不会扩大画布,旋转90/270度时会裁剪掉超出原始尺寸的部分,添加expand=True参数可以自动调整画布尺寸适配旋转后的图片。

内容的提问来源于stack exchange,提问作者Ian Kurtis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 23:54:06