67 lines
2.8 KiB
Python
67 lines
2.8 KiB
Python
import aioboto3
|
||
import asyncio
|
||
import logging
|
||
import os
|
||
|
||
import aiohttp
|
||
from app.config import settings
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
async def download_and_upload_stream(url: str, key_name: str) -> bool:
|
||
"""
|
||
Скачивает аудиофайл по URL потоками и передаёт в upload_file_to_s3 для загрузки.
|
||
"""
|
||
try:
|
||
logger.info(f"[INFO] Начало скачивания {url}")
|
||
async with aiohttp.ClientSession() as http_session:
|
||
async with http_session.get(url) as resp:
|
||
resp.raise_for_status()
|
||
|
||
# читаем файл по частям и собираем в bytes
|
||
chunks = []
|
||
while True:
|
||
chunk = await resp.content.read(1024 * 1024) # 1 МБ
|
||
if not chunk:
|
||
break
|
||
chunks.append(chunk)
|
||
file_bytes = b"".join(chunks)
|
||
|
||
logger.info(f"[INFO] Скачивание {url} завершено, размер {len(file_bytes)} байт")
|
||
|
||
# передаём в функцию загрузки с retry
|
||
success = await upload_file_to_s3(file_bytes, key_name)
|
||
return success
|
||
|
||
except Exception as e:
|
||
logger.error(f"[FAILED] Не удалось скачать или загрузить {url}: {e}")
|
||
return False
|
||
|
||
async def upload_file_to_s3(file_bytes: bytes, key_name: str) -> bool:
|
||
"""
|
||
Асинхронно загружает файл в S3 с ретраями.
|
||
Возвращает True при успехе, False при ошибке.
|
||
"""
|
||
session = aioboto3.Session()
|
||
for attempt in range(1, settings.MAX_RETRIES + 1):
|
||
try:
|
||
logger.info(f"Попытка {attempt} загрузки {key_name} в S3")
|
||
#logger.info(f"Параметры S3: {S3_ENDPOINT_URL}, {S3_BUCKET_NAME}, {AWS_REGION}")
|
||
|
||
async with session.client(
|
||
"s3",
|
||
endpoint_url=settings.S3_ENDPOINT_URL,
|
||
aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
|
||
aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
|
||
region_name=settings.AWS_REGION
|
||
) as s3:
|
||
await s3.put_object(Bucket=settings.S3_BUCKET_NAME, Key=key_name, Body=file_bytes)
|
||
logger.info(f"[OK] Файл {key_name} загружен в S3!")
|
||
return True
|
||
except Exception as e:
|
||
logger.exception(f"[ERROR] Попытка {attempt} для {key_name} не удалась: {e}")
|
||
if attempt < settings.MAX_RETRIES:
|
||
await asyncio.sleep(settings.RETRY_DELAY)
|
||
else:
|
||
logger.error(f"[FAILED] Файл {key_name} не удалось загрузить после {settings.MAX_RETRIES} попыток")
|
||
return False |