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

求助:无法从Telegram将图片下载为字节流/Base64格式

Telegram图片转字节流/Base64失败问题

我想从Telegram下载图片并直接转换为字节流(bytes)或Base64格式,不想保存为本地图片文件,但尝试后代码执行失败。以下是我写的代码:

channels = ['channel_name']
async with TelegramClient(username, api_id, api_hash) as client:    
    # 遍历Telegram频道
    for channel in channels:
        try:
            async with client.takeout() as takeout:
                async for message in takeout.iter_messages(channel,  wait_time=0):
                    try:
                        # await client.download_media(message.media, temp_folder+channel+str(message.id))
                        print(message.media)
                        data = await client.download_file(
                            message.media,
                            bytes,
                            progress_callback=callback
                        )                      

                        image = mpimg.imread(io.BytesIO(data), format='JPEG')
                        plt.imshow(image)
                    except FileReferenceExpiredError:
                        print('发生FileReferenceExpiredError异常')
        except errors.TakeoutInitDelayError as e:
            print('必须等待', e.seconds, '秒后才能执行导出')

程序先打印message.media,随后抛出如下错误:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
D:\TEMP\hkay\Temp\ipykernel_79040\2965379116.py in <module>
     53                         # await client.download_media(message.media, temp_folder+channel+str(message.id))
     54                         print(message.media)
---&gt; 55                         data = await client.download_file(
     56                             message,
     57                             bytes,

~\AppData\Roaming\Python\Python39\site-packages\telethon\client\downloads.py in download_file(self, input_location, file, part_size_kb, file_size, progress_callback, dc_id, key, iv)
    490                 print(data[:16])
    491         """
--&gt; 492         return await self._download_file(
    493             input_location,
    494             file,

~\AppData\Roaming\Python\Python39\site-packages\telethon\client\downloads.py in _download_file(self, input_location, file, part_size_kb, file_size, progress_callback, dc_id, key, iv, msg_data)
    547 
    548                 if progress_callback:
--&gt; 549                     r = progress_callback(f.tell(), file_size)
    550                     if inspect.isawaitable(r):
    551                         await r

D:\TEMP\hkay\Temp\ipykernel_79040\1493750919.py in callback(current, total, channel_name)
     33 def callback(current, total, channel_name=channel):
     34     print('Downloaded from',channel,'-', 'message_id:', message.id, ' ', current, 'out of', total,
---&gt; 35           'bytes: {:.2%}'.format(current / total))
     36 
     37 # Connect to API with Client

TypeError: unsupported operand type(s) for /: 'int' and 'NoneType'

编辑1:
移除progress_callback后,出现新错误:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
~\AppData\Roaming\Python\Python39\site-packages\telethon\utils.py in _get_file_info(location)
    800     try:
--&gt; 801         if location.SUBCLASS_OF_ID == 0x1523d462:
    802             return _FileInfo(None, location, None)  # crc32(b'InputFileLocation'):

AttributeError: 'NoneType' object has no attribute 'SUBCLASS_OF_ID'

During handling of the above exception, another exception occurred:

TypeError                                 Traceback (most recent call last)
D:\TEMP\hkhan\Temp\ipykernel_79040\1631659142.py in <module>
     53                         #await client.download_media(message.media, temp_folder+channel+str(message.id))
     54 
---&gt; 55                         data = await client.download_file(message.media
     56                                                           ,bytes
     57                                                          )                      

~\AppData\Roaming\Python\Python39\site-packages\telethon\client\downloads.py in download_file(self, input_location, file, part_size_kb, file_size, progress_callback, dc_id, key, iv)
    490                 print(data[:16])
    491         """
--&gt; 492         return await self._download_file(
    493             input_location,
    494             file,

~\AppData\Roaming\Python\Python39\site-packages\telethon\client\downloads.py in _download_file(self, input_location, file, part_size_kb, file_size, progress_callback, dc_id, key, iv, msg_data)
    538 
    539         try:
--&gt; 540             async for chunk in self._iter_download(
    541                     input_location, request_size=part_size, dc_id=dc_id, msg_data=msg_data):
    542                 if iv and key:

~\AppData\Roaming\Python\Python39\site-packages\telethon\client\downloads.py in _iter_download(self, file, offset, stride, limit, chunk_size, request_size, file_size, dc_id, msg_data)
    680             msg_data: tuple = None
    681     ):
--&gt; 682         info = utils._get_file_info(file)
    683         if info.dc_id is not None:
    684             dc_id = info.dc_id

~\AppData\Roaming\Python\Python39\site-packages\telethon\utils.py in _get_file_info(location)
    802             return _FileInfo(None, location, None)  # crc32(b'InputFileLocation'):
    803     except AttributeError:
--&gt; 804         _raise_cast_fail(location, 'InputFileLocation')
    805 
    806     if isinstance(location, types.Message):

~\AppData\Roaming\Python\Python39\site-packages\telethon\utils.py in _raise_cast_fail(entity, target)
    136 
    137 def _raise_cast_fail(entity, target):
--&gt; 138     raise TypeError('Cannot cast {} to any kind of {}.'.format(
    139         type(entity).__name__, target))
    140 

TypeError: Cannot cast NoneType to any kind of InputFileLocation.

解决步骤

1. 过滤非图片消息

第二个错误说明遍历的消息里存在不带媒体的内容,message.media为None,必须先判断只处理图片类型的消息:

async for message in takeout.iter_messages(channel, wait_time=0):
    # 仅处理图片消息
    if message.photo:
        try:
            # 后续处理逻辑
            pass
        except FileReferenceExpiredError:
            print('发生FileReferenceExpiredError异常')

2. 替换download_file为download_media

download_file要求传入InputFileLocation类型参数,而download_media可以直接接收message.photo,并且支持直接返回字节流,无需额外配置:

# 直接获取图片字节流
data = await client.download_media(message.photo, bytes)

3. 修复进度回调的除数问题

如果要保留进度回调,需先判断total是否为空,避免除以None报错:

def callback(current, total, channel_name, message_id):
    if total is None:
        print(f'从{channel_name}下载 - message_id: {message_id} 已下载 {current} 字节')
    else:
        print(f'从{channel_name}下载 - message_id: {message_id}  {current}/{total} 字节: {current/total:.2%}')

完整修正代码

import io
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from telethon import TelegramClient, errors
from telethon.errors import FileReferenceExpiredError

def callback(current, total, channel_name, message_id):
    if total is None:
        print(f'从{channel_name}下载 - message_id: {message_id} 已下载 {current} 字节')
    else:
        print(f'从{channel_name}下载 - message_id: {message_id}  {current}/{total} 字节: {current/total:.2%}')

async def main():
    username = '你的用户名'
    api_id = 123456  # 替换为你的API_ID
    api_hash = '你的API_HASH'
    channels = ['channel_name']
    
    async with TelegramClient(username, api_id, api_hash) as client:    
        for channel in channels:
            try:
                async with client.takeout() as takeout:
                    async for message in takeout.iter_messages(channel, wait_time=0):
                        if message.photo:
                            try:
                                print(message.photo)
                                # 下载为字节流
                                data = await client.download_media(
                                    message.photo,
                                    bytes,
                                    progress_callback=lambda cur, tot: callback(cur, tot, channel, message.id)
                                )                      

                                # 加载并显示图片
                                image = mpimg.imread(io.BytesIO(data), format='JPEG')
                                plt.imshow(image)
                                plt.show()
                            except FileReferenceExpiredError:
                                print('发生FileReferenceExpiredError异常')
            except errors.TakeoutInitDelayError as e:
                print('必须等待', e.seconds, '秒后才能执行导出')

if __name__ == '__main__':
    import asyncio
    asyncio.run(main())

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 19:29:44