Add file downloading

This commit is contained in:
2022-01-09 20:55:24 +03:00
parent cefc84af81
commit bb300daedd
5 changed files with 67 additions and 2 deletions

View File

@@ -16,4 +16,4 @@ class CachedFile(ormar.Model):
id: int = ormar.Integer(primary_key=True) # type: ignore id: int = ormar.Integer(primary_key=True) # type: ignore
object_id: int = ormar.Integer() # type: ignore object_id: int = ormar.Integer() # type: ignore
object_type: str = ormar.String(max_length=8) # type: ignore object_type: str = ormar.String(max_length=8) # type: ignore
data = ormar.JSON() data: dict = ormar.JSON() # type: ignore

View File

@@ -5,7 +5,7 @@ from typing import Optional
from app.models import CachedFile from app.models import CachedFile
from app.services.caption_getter import get_caption from app.services.caption_getter import get_caption
from app.services.downloader import download from app.services.downloader import download
from app.services.files_uploader import upload_file from app.services.files_client import upload_file
from app.services.library_client import get_books, get_book, Book from app.services.library_client import get_books, get_book, Book

View File

@@ -25,3 +25,19 @@ async def download(
name = content_disposition.replace("attachment; filename=", "") name = content_disposition.replace("attachment; filename=", "")
return response.content, name return response.content, name
async def get_filename(book_id: int, file_type: str) -> Optional[str]:
headers = {"Authorization": env_config.DOWNLOADER_API_KEY}
async with httpx.AsyncClient() as client:
response = await client.get(
f"{env_config.DOWNLOADER_URL}/filename/{book_id}/{file_type}",
headers=headers,
timeout=5 * 60,
)
if response.status_code != 200:
return None
return response.text

View File

@@ -1,4 +1,5 @@
from datetime import datetime from datetime import datetime
from typing import Optional
import httpx import httpx
from pydantic import BaseModel from pydantic import BaseModel
@@ -29,3 +30,19 @@ async def upload_file(content: bytes, filename: str, caption: str) -> UploadedFi
) )
return UploadedFile.parse_obj(response.json()) return UploadedFile.parse_obj(response.json())
async def download_file(chat_id: int, message_id: int) -> Optional[bytes]:
headers = {"Authorization": env_config.FILES_SERVER_API_KEY}
async with httpx.AsyncClient(timeout=60) as client:
response = await client.get(
f"{env_config.FILES_SERVER_URL}"
f"/api/v1/files/download_by_message/{chat_id}/{message_id}",
headers=headers,
)
if response.status_code != 200:
return None
return response.content

View File

@@ -1,11 +1,15 @@
from fastapi import APIRouter, Depends, HTTPException, BackgroundTasks, status from fastapi import APIRouter, Depends, HTTPException, BackgroundTasks, status
from starlette.responses import Response
from asyncpg import exceptions from asyncpg import exceptions
from app.depends import check_token from app.depends import check_token
from app.models import CachedFile as CachedFileDB from app.models import CachedFile as CachedFileDB
from app.serializers import CachedFile, CreateCachedFile from app.serializers import CachedFile, CreateCachedFile
from app.services.cache_updater import CacheUpdater from app.services.cache_updater import CacheUpdater
from app.services.downloader import get_filename
from app.services.files_client import download_file as download_file_from_cache
router = APIRouter( router = APIRouter(
@@ -28,6 +32,34 @@ async def get_cached_file(object_id: int, object_type: str):
return cached_file return cached_file
@router.get("/download/{object_id}/{object_type}")
async def download_cached_file(object_id: int, object_type: str):
cached_file = await CachedFileDB.objects.get_or_none(
object_id=object_id, object_type=object_type
)
if not cached_file:
cached_file = await CacheUpdater.cache_file(object_id, object_type)
if not cached_file:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
cache_data = cached_file.data
data = await download_file_from_cache(
cache_data["chat_id"], cache_data["message_id"]
)
if data is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
filename = await get_filename(object_id, object_type)
return Response(
data, headers={"Content-Disposition": f"attachment; filename={filename}"}
)
@router.delete("/{object_id}/{object_type}", response_model=CachedFile) @router.delete("/{object_id}/{object_type}", response_model=CachedFile)
async def delete_cached_file(object_id: int, object_type: str): async def delete_cached_file(object_id: int, object_type: str):
cached_file = await CachedFileDB.objects.get( cached_file = await CachedFileDB.objects.get(