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

如何在aiogram的FSM流程中暂存用户照片并后续回传(不存磁盘)

解决aiogram中FSM暂存照片并后续回传的问题

核心思路是利用aiogram的FSMContext存储照片相关数据,完全无需写入本地磁盘。下面提供两种常用实现方案:

方案一:存储照片file_id(推荐)

Telegram Bot API支持直接通过file_id发送媒体,这种方式最轻量化,无需处理二进制数据,资源消耗最低。

接收照片的处理函数

@dp.message_handler(content_types=['photo'], state=UserState.photo)
async def get_photo(message: types.Message, state: FSMContext):
    # 获取最高分辨率照片的file_id
    photo_file_id = message.photo[-1].file_id
    # 将file_id存入FSM状态
    await state.update_data(photo_file_id=photo_file_id)
    
    # 可选:测试发送,验证存储成功
    await bot.send_photo(message.chat.id, photo_file_id)
    
    await UserState.main_text.set()

后续步骤回传照片的处理函数

@dp.message_handler(state=UserState.main_text)
async def process_main_text(message: types.Message, state: FSMContext):
    # 从FSM状态中取出照片file_id
    data = await state.get_data()
    photo_file_id = data.get('photo_file_id')
    
    # 回传照片给用户
    if photo_file_id:
        await bot.send_photo(message.chat.id, photo_file_id)
    
    # 其他业务逻辑...
    await state.finish()

方案二:存储照片二进制数据(适合需本地处理的场景)

如果需要对照片进行裁剪、压缩等本地操作,可以将二进制数据存入内存对象,再存入FSM状态。

接收照片的处理函数

from io import BytesIO

@dp.message_handler(content_types=['photo'], state=UserState.photo)
async def get_photo(message: types.Message, state: FSMContext):
    # 获取照片的远程文件对象
    photo_file = await bot.get_file(message.photo[-1].file_id)
    # 下载二进制数据到内存中的BytesIO对象
    photo_bytes = BytesIO(await bot.download_file(photo_file.file_path))
    
    # 将二进制数据转为bytes后存入FSM(BytesIO对象无法直接序列化)
    await state.update_data(photo_bytes=photo_bytes.getvalue())
    
    # 可选:测试发送,注意重置文件指针到开头
    photo_bytes.seek(0)
    await bot.send_photo(message.chat.id, photo_bytes)
    
    await UserState.main_text.set()

后续步骤回传照片的处理函数

from io import BytesIO

@dp.message_handler(state=UserState.main_text)
async def process_main_text(message: types.Message, state: FSMContext):
    data = await state.get_data()
    photo_bytes_data = data.get('photo_bytes')
    
    if photo_bytes_data:
        # 将bytes转回BytesIO对象用于发送
        photo_bytes = BytesIO(photo_bytes_data)
        await bot.send_photo(message.chat.id, photo_bytes)
    
    # 其他业务逻辑...
    await state.finish()

注意事项

  • 优先选择方案一,file_id存储更高效,Telegram会缓存媒体文件,重复发送无需重新上传。
  • 若使用二进制存储,需注意FSM存储的限制:用MemoryStorage时数据存在内存,机器人重启会丢失;用Redis等持久化存储时,要确保序列化支持bytes类型。
  • 使用BytesIO对象发送时,必须调用seek(0)重置指针到开头,否则会因指针在末尾导致读取不到数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 10:12:44