-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsender.py
91 lines (67 loc) · 3.3 KB
/
sender.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import asyncio
import logging.config
import os
from typing import Generator
from urllib.parse import urljoin
import aiohttp
import configargparse as configargparse
from aiofile import async_open
from aiologger.loggers.json import JsonLogger
from dotenv import load_dotenv
CHUNK_SIZE = 2 ** 16 # Размер порции файла для считывания в ОЗУ, в байтах
def get_args() -> configargparse.Namespace:
"""Получаем аргументы из командной строки"""
load_dotenv()
parser = configargparse.ArgParser()
parser.add('--protocol', type=str, required=False, choices=['http', 'https'], default='http',
help='Протокол файлового сервера (default: %(default)s)')
parser.add('--host', type=str, required=False, default='localhost',
help='Хост файлового сервера (default: %(default)s)')
parser.add('--port', type=int, required=False, default=os.getenv('FILE_SERVICE_PORT'),
help='Порт файлового сервера (default: %(default)s)')
parser.add('--url', type=str, required=False, default='files/',
help='Урл для доступа к методу сохранения файла (default: %(default)s)')
parser.add('--chunk_size', type=int, required=False, default=os.getenv('FILE_SERVICE_CHUNK'),
help='Размер порции файла для считывания в ОЗУ, в байтах (default: %(default)s)')
parser.add('--path', type=str, required=True,
help='Файл для сохранения в файловом сервисе')
return parser.parse_args()
async def file_sender(file_name: str, chunk_size: int) -> Generator[bytes, None, None]:
"""
Генератор считывания файла по частям
Параметры:
file_name (str): имя файла, включая путь
chunk_size (int): размер порции для считывания файла в память
Возвращаемое значение:
chunk (bytes): часть байтового потока файла
"""
async with async_open(file_name, 'rb') as f:
chunk = await f.read(chunk_size)
while chunk:
yield chunk
chunk = await f.read(chunk_size)
async def main() -> None:
"""Функция генерации post-запроса в адрес файлового сервиса"""
logger = JsonLogger.with_default_handlers(
level=logging.DEBUG,
)
args = get_args()
url = urljoin(f'{args.protocol}://{args.host}:{args.port}', args.url)
headers = {
'CONTENT-DISPOSITION': f'attachment;filename={os.path.basename(args.path)}',
}
async with aiohttp.ClientSession() as session:
async with session.post(
url,
headers=headers,
data=file_sender(file_name=args.path, chunk_size=args.chunk_size)
) as resp:
await logger.info(await resp.text())
await logger.shutdown()
if __name__ == '__main__':
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
asyncio.run(main())
except KeyboardInterrupt:
pass