Я работаю над методом телемарафона download_media для загрузки изображений и видео. Он работает нормально (как и ожидалось). Теперь я хочу напрямую загрузить download_media в папку на моем диске Google.
Пример кода выглядит примерно так:
from telethon import TelegramClient, events, sync
from telethon.tl.types import PeerUser, PeerChat, PeerChannel
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
gauth = GoogleAuth()
drive = GoogleDrive(gauth)
gfile = drive.CreateFile({'parents': [{'id': 'drive_directory_path'}]})
api_id = #####
api_hash = ##########
c = client.get_entity(PeerChannel(1234567)) # some random channel id
for m in client.iter_messages(c):
if m.photo:
# below is the one way and it works
# m.download_media("Media/")
# I want to try something like this - below code
gfile.SetContentFile(m.media)
gfile.Upload()
Этот код не работает. Как я могу определить объект диска Google для download_media?
Заранее спасибо. Любезно помочь!
@LindaLawton-DaImTo, аутентификация на Диске не проблема. То, как я упоминаю gfile.SetContentFile(m.media)
, неверно, мы определяем путь к изображению в этом аргументе. Я не уверен, как правильно написать код для прямой загрузки медиафайлов сообщений телеграммы через диск. Не могли бы вы помочь мне с этим?
Это не так работает. Ни одна из этих библиотек не знает, как общаться друг с другом. Что вы можете сделать, проверьте исходный код того, как телемарафон сохраняет байты и как pydrive затем загружает байты файла и отправляет каждый байт файла по мере его получения. Но вы не можете напрямую загружать их с телемарафона на гугл диск.
Основная проблема заключается в том, что, согласно документации PyDrive, setContentFile() ожидает string
с локальным путем к файлу, а затем просто использует open(), поэтому вы должны использовать это с локальными файлами. В своем коде вы пытаетесь передать ему медиафайл, поэтому он не будет работать.
Чтобы загрузить файл bytes
с помощью PyDrive, вам нужно преобразовать его в BytesIO и отправить как content
. Пример с локальным файлом будет выглядеть так:
drive = GoogleDrive(gauth)
file = drive.CreateFile({'mimeType':'image/jpeg', 'title':'example.jpg'})
filebytes = open('example.jpg', 'rb').read()
file.content = io.BytesIO(filebytes)
file.Upload()
Обычно вам не нужно делать это таким образом, потому что setContentFile()
делает открытие и преобразование за вас, но это должно дать вам представление о том, что если вы получите медиафайл bytes
, вы можете просто преобразовать его и назначить его file.content
, а затем вы можете загрузить его.
Теперь, если вы посмотрите на документацию Telethon, вы увидите, что download_media()
принимает file
аргумент, который вы можете установить в bytes
:
файл (str | файл, необязательно):
Путь к выходному файлу, каталог или объект, подобный потоку. Если путь существует и является файлом, он будет перезаписан. Если файл имеет тип bytes, он будет загружен в память как строка байтов (например, файл=байты).
Таким образом, вы должны иметь возможность вызывать m.download_media(file=bytes)
, чтобы получить объект bytes. Глядя еще глубже на исходный код Telethon, кажется, что это действительно возвращает BytesIO
объект. Имея это в виду, вы можете попробовать следующее изменение в своем цикле:
for m in client.iter_messages(c):
if m.photo:
gfile.content = io.BytesIO(m.download_media(file=bytes))
gfile.Upload()
Обратите внимание, что я тестировал только сторону PyDrive, поскольку в настоящее время у меня нет доступа к API Telegram, но, глядя на документы, я считаю, что это должно работать. Позвольте мне знать, что происходит.
Спасибо за подробное объяснение. Я попробовал предложенный вами код if m.video: gfile = drive.CreateFile({'title': "video.mp4", 'parents': [{'id': 'path_to_drive'}]}) gfile.content = m.download_media(file=bytes) gfile.Upload()
Однако после успешной аутентификации я получаю следующую ошибку: gfile.Upload() AttributeError: 'bytes' object has no attribute 'seek'
Не могли бы вы помочь мне с этим?
Хотя, gfile.content = io.BytesIO(m.download_media(file=bytes))
gfile.Upload()
Это сработало, и теперь загрузка медиа загружается напрямую через диск. Большое спасибо!
Приятно слышать! Я думал, что download_media
уже превратится в BytesIO
, но я ошибался. Я исправил свой ответ для дальнейшего использования.
Обратите внимание, что можно передать экземпляр io.BytesIO()
в качестве файла, в котором download_media
должен сохранять данные, поэтому нет необходимости использовать bytes
. Тем не менее отличный ответ.
Добро пожаловать в стек, пожалуйста, определите «Этот код не работает». Нам нужно знать, что не работает, есть ли ошибки, если да, то в чем ошибка, файл не загружен? Из того, что я вижу, вам не хватает некоторых функций авторизации. Что, вероятно, означает, что вы получаете неавторизованную ошибку.