From 5dacbdd2a5a1401083dc064195690327d581591f Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Sun, 8 Apr 2018 17:22:10 +0300 Subject: [PATCH] Returned back `InputFile.from_url(url)` method. --- aiogram/types/input_file.py | 83 +++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/aiogram/types/input_file.py b/aiogram/types/input_file.py index ff5ab1f0..9b510b09 100644 --- a/aiogram/types/input_file.py +++ b/aiogram/types/input_file.py @@ -1,10 +1,15 @@ import io import logging import os +import time + +import aiohttp from . import base from ..bot import api +CHUNK_SIZE = 65536 + log = logging.getLogger('aiogram') @@ -76,6 +81,84 @@ class InputFile(base.TelegramObject): """ return self.file + @classmethod + async def from_url(cls, url, filename=None, chunk_size=65536): + """ + Download file from URL + + Manually is not required action. You can send urls instead! + + :param url: target URL + :param filename: optional. set custom file name + :param chunk_size: + + :return: InputFile + """ + conf = { + 'downloaded': True, + 'url': url + } + + # Let's do magic with the filename + if filename: + filename_prefix, _, ext = filename.rpartition('.') + file_suffix = '.' + ext if ext else '' + else: + filename_prefix, _, ext = url.rpartition('/')[-1].rpartition('.') + file_suffix = '.' + ext if ext else '' + filename = filename_prefix + file_suffix + + async with aiohttp.ClientSession() as session: + start = time.time() + async with session.get(url) as response: + # Save file in memory + file = await cls._process_stream(response, io.BytesIO(), chunk_size=chunk_size) + + log.debug(f"File successful downloaded at {round(time.time() - start, 2)} seconds from '{url}'") + return cls(file, filename, conf=conf) + + def save(self, filename, chunk_size=65536): + """ + Write file to disk + + :param filename: + :param chunk_size: + """ + with open(filename, 'wb') as fp: + while True: + # Chunk writer + data = self.file.read(chunk_size) + if not data: + break + fp.write(data) + # Flush all data + fp.flush() + + # Go to start of file. + if self.file.seekable(): + self.file.seek(0) + + @classmethod + async def _process_stream(cls, response, writer, chunk_size=65536): + """ + Transfer data + + :param response: + :param writer: + :param chunk_size: + :return: + """ + while True: + chunk = await response.content.read(chunk_size) + if not chunk: + break + writer.write(chunk) + + if writer.seekable(): + writer.seek(0) + + return writer + def to_python(self): raise TypeError('Object of this type is not exportable!')